--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -7,16 +7,17 @@
/* A namespace class for static layout utilities. */
#include "mozilla/Util.h"
#include "jsapi.h"
#include "jsdbgapi.h"
#include "jsfriendapi.h"
+#include "Layers.h"
#include "nsJSUtils.h"
#include "nsCOMPtr.h"
#include "nsAString.h"
#include "nsPrintfCString.h"
#include "nsIScriptGlobalObject.h"
#include "nsIScriptContext.h"
#include "nsDOMCID.h"
#include "nsContentUtils.h"
--- a/content/html/content/src/nsHTMLCanvasElement.cpp
+++ b/content/html/content/src/nsHTMLCanvasElement.cpp
@@ -21,17 +21,16 @@
#include "nsJSUtils.h"
#include "nsMathUtils.h"
#include "nsStreamUtils.h"
#include "mozilla/Preferences.h"
#include "mozilla/Telemetry.h"
#include "nsFrameManager.h"
#include "nsDisplayList.h"
-#include "ImageLayers.h"
#include "BasicLayers.h"
#include "imgIEncoder.h"
#include "nsIWritablePropertyBag2.h"
#define DEFAULT_CANVAS_WIDTH 300
#define DEFAULT_CANVAS_HEIGHT 150
--- a/content/media/VideoFrameContainer.h
+++ b/content/media/VideoFrameContainer.h
@@ -2,17 +2,17 @@
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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 VIDEOFRAMECONTAINER_H_
#define VIDEOFRAMECONTAINER_H_
-#include "ImageLayers.h"
+#include "ImageContainer.h"
#include "mozilla/Mutex.h"
#include "mozilla/TimeStamp.h"
#include "nsISupportsImpl.h"
#include "gfxPoint.h"
class nsHTMLMediaElement;
namespace mozilla {
--- a/content/media/VideoSegment.h
+++ b/content/media/VideoSegment.h
@@ -2,17 +2,17 @@
/* 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 MOZILLA_VIDEOSEGMENT_H_
#define MOZILLA_VIDEOSEGMENT_H_
#include "MediaSegment.h"
-#include "ImageLayers.h"
+#include "ImageContainer.h"
namespace mozilla {
class VideoFrame {
public:
typedef mozilla::layers::Image Image;
VideoFrame(already_AddRefed<Image> aImage, const gfxIntSize& aIntrinsicSize)
--- a/content/media/nsBuiltinDecoder.h
+++ b/content/media/nsBuiltinDecoder.h
@@ -190,21 +190,26 @@ destroying the nsBuiltinDecoder object.
#include "nsSize.h"
#include "prlog.h"
#include "gfxContext.h"
#include "gfxRect.h"
#include "MediaResource.h"
#include "nsMediaDecoder.h"
#include "nsHTMLMediaElement.h"
#include "mozilla/ReentrantMonitor.h"
-#include "ImageLayers.h"
-class nsAudioStream;
-typedef mozilla::layers::Image Image;
-typedef mozilla::layers::ImageContainer ImageContainer;
+namespace mozilla {
+namespace layers {
+class Image;
+} //namespace
+} //namespace
+
+typedef mozilla::layers::Image Image;
+
+class nsAudioStream;
static inline bool IsCurrentThread(nsIThread* aThread) {
return NS_GetCurrentThread() == aThread;
}
// Decoder backends must implement this class to perform the codec
// specific parts of decoding the video/audio format.
class nsDecoderStateMachine : public nsRunnable
--- a/content/media/nsBuiltinDecoderReader.cpp
+++ b/content/media/nsBuiltinDecoderReader.cpp
@@ -143,22 +143,22 @@ VideoData* VideoData::Create(nsVideoInfo
nsAutoPtr<VideoData> v(new VideoData(aOffset,
aTime,
aEndTime,
aKeyframe,
aTimecode,
aInfo.mDisplay));
// Currently our decoder only knows how to output to PLANAR_YCBCR
// format.
- Image::Format format = Image::PLANAR_YCBCR;
+ ImageFormat format = ImageFormat::PLANAR_YCBCR;
v->mImage = aContainer->CreateImage(&format, 1);
if (!v->mImage) {
return nullptr;
}
- NS_ASSERTION(v->mImage->GetFormat() == Image::PLANAR_YCBCR,
+ NS_ASSERTION(v->mImage->GetFormat() == ImageFormat::PLANAR_YCBCR,
"Wrong format?");
PlanarYCbCrImage* videoImage = static_cast<PlanarYCbCrImage*>(v->mImage.get());
PlanarYCbCrImage::Data data;
const YCbCrBuffer::Plane &Y = aBuffer.mPlanes[0];
const YCbCrBuffer::Plane &Cb = aBuffer.mPlanes[1];
const YCbCrBuffer::Plane &Cr = aBuffer.mPlanes[2];
--- a/content/media/nsBuiltinDecoderReader.h
+++ b/content/media/nsBuiltinDecoderReader.h
@@ -14,17 +14,17 @@
// Stores info relevant to presenting media frames.
class nsVideoInfo {
public:
nsVideoInfo()
: mAudioRate(44100),
mAudioChannels(2),
mDisplay(0,0),
- mStereoMode(mozilla::layers::STEREO_MODE_MONO),
+ mStereoMode(mozilla::STEREO_MODE_MONO),
mHasAudio(false),
mHasVideo(false)
{}
// Returns true if it's safe to use aPicture as the picture to be
// extracted inside a frame of size aFrame, and scaled up to and displayed
// at a size of aDisplay. You should validate the frame, picture, and
// display regions before using them to display video frames.
@@ -38,17 +38,17 @@ public:
// Number of audio channels.
PRUint32 mAudioChannels;
// Size in pixels at which the video is rendered. This is after it has
// been scaled by its aspect ratio.
nsIntSize mDisplay;
// Indicates the frame layout for single track stereo videos.
- mozilla::layers::StereoMode mStereoMode;
+ mozilla::StereoMode mStereoMode;
// True if we have an active audio bitstream.
bool mHasAudio;
// True if we have an active video bitstream.
bool mHasVideo;
};
@@ -457,17 +457,17 @@ public:
public:
VideoQueueMemoryFunctor() : mResult(0) {}
virtual void* operator()(void* anObject) {
const VideoData* v = static_cast<const VideoData*>(anObject);
if (!v->mImage) {
return nullptr;
}
- NS_ASSERTION(v->mImage->GetFormat() == mozilla::layers::Image::PLANAR_YCBCR,
+ NS_ASSERTION(v->mImage->GetFormat() == mozilla::ImageFormat::PLANAR_YCBCR,
"Wrong format?");
mozilla::layers::PlanarYCbCrImage* vi = static_cast<mozilla::layers::PlanarYCbCrImage*>(v->mImage.get());
mResult += vi->GetDataSize();
return nullptr;
}
PRInt64 mResult;
--- a/content/media/nsMediaDecoder.h
+++ b/content/media/nsMediaDecoder.h
@@ -4,16 +4,17 @@
* 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/. */
#if !defined(nsMediaDecoder_h_)
#define nsMediaDecoder_h_
#include "mozilla/ReentrantMonitor.h"
#include "VideoFrameContainer.h"
#include "MediaStreamGraph.h"
+#include "nsIObserver.h"
class nsHTMLMediaElement;
class nsIStreamListener;
class nsTimeRanges;
class nsIMemoryReporter;
class nsIPrincipal;
class nsITimer;
--- a/content/media/webrtc/MediaEngineDefault.cpp
+++ b/content/media/webrtc/MediaEngineDefault.cpp
@@ -2,16 +2,17 @@
* 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 "MediaEngineDefault.h"
#include "nsCOMPtr.h"
#include "nsDOMFile.h"
#include "nsILocalFile.h"
+#include "Layers.h"
#ifdef MOZ_WIDGET_ANDROID
#include "AndroidBridge.h"
#include "nsISupportsUtils.h"
#endif
#define WIDTH 320
#define HEIGHT 240
@@ -89,17 +90,17 @@ MediaEngineDefaultVideoSource::Start(Sou
mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
if (!mTimer) {
return NS_ERROR_FAILURE;
}
mSource = aStream;
// Allocate a single blank Image
- layers::Image::Format format = layers::Image::PLANAR_YCBCR;
+ ImageFormat format = ImageFormat::PLANAR_YCBCR;
mImageContainer = layers::LayerManager::CreateImageContainer();
nsRefPtr<layers::Image> image = mImageContainer->CreateImage(&format, 1);
int len = ((WIDTH * HEIGHT) * 3 / 2);
mImage = static_cast<layers::PlanarYCbCrImage*>(image.get());
PRUint8* frame = (PRUint8*) PR_Malloc(len);
memset(frame, 0x80, len); // Gray
@@ -113,17 +114,17 @@ MediaEngineDefaultVideoSource::Start(Sou
data.mYStride = WIDTH * lumaBpp / 8.0;
data.mCbCrStride = WIDTH * chromaBpp / 8.0;
data.mCbChannel = frame + HEIGHT * data.mYStride;
data.mCrChannel = data.mCbChannel + HEIGHT * data.mCbCrStride / 2;
data.mCbCrSize = gfxIntSize(WIDTH / 2, HEIGHT / 2);
data.mPicX = 0;
data.mPicY = 0;
data.mPicSize = gfxIntSize(WIDTH, HEIGHT);
- data.mStereoMode = layers::STEREO_MODE_MONO;
+ data.mStereoMode = STEREO_MODE_MONO;
// SetData copies data, so we can free the frame
mImage->SetData(data);
PR_Free(frame);
// AddTrack takes ownership of segment
VideoSegment *segment = new VideoSegment();
segment->AppendFrame(image.forget(), USECS_PER_S / FPS, gfxIntSize(WIDTH, HEIGHT));
--- a/content/media/webrtc/MediaEngineWebRTCVideo.cpp
+++ b/content/media/webrtc/MediaEngineWebRTCVideo.cpp
@@ -1,13 +1,14 @@
/* 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 "MediaEngineWebRTC.h"
+#include "Layers.h"
namespace mozilla {
/**
* Webrtc video source.
*/
NS_IMPL_THREADSAFE_ISUPPORTS1(MediaEngineWebRTCVideoSource, nsIRunnable)
@@ -42,17 +43,17 @@ MediaEngineWebRTCVideoSource::DeliverFra
}
// Check for proper state.
if (mState != kStarted) {
return 0;
}
// Create a video frame and append it to the track.
- layers::Image::Format format = layers::Image::PLANAR_YCBCR;
+ ImageFormat format = ImageFormat::PLANAR_YCBCR;
nsRefPtr<layers::Image> image = mImageContainer->CreateImage(&format, 1);
layers::PlanarYCbCrImage* videoImage = static_cast<layers::PlanarYCbCrImage*>(image.get());
PRUint8* frame = static_cast<PRUint8*> (buffer);
const PRUint8 lumaBpp = 8;
const PRUint8 chromaBpp = 4;
@@ -62,17 +63,17 @@ MediaEngineWebRTCVideoSource::DeliverFra
data.mYStride = mWidth * lumaBpp/ 8;
data.mCbCrStride = mWidth * chromaBpp / 8;
data.mCbChannel = frame + mHeight * data.mYStride;
data.mCrChannel = data.mCbChannel + mHeight * data.mCbCrStride / 2;
data.mCbCrSize = gfxIntSize(mWidth/ 2, mHeight/ 2);
data.mPicX = 0;
data.mPicY = 0;
data.mPicSize = gfxIntSize(mWidth, mHeight);
- data.mStereoMode = layers::STEREO_MODE_MONO;
+ data.mStereoMode = STEREO_MODE_MONO;
videoImage->SetData(data);
VideoSegment segment;
segment.AppendFrame(image.forget(), 1, gfxIntSize(mWidth, mHeight));
mSource->AppendToTrack(mTrackID, &(segment));
return 0;
}
--- a/dom/camera/CameraPreview.cpp
+++ b/dom/camera/CameraPreview.cpp
@@ -1,14 +1,14 @@
/* 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 "CameraPreview.h"
-
+#include "Layers.h"
#define DOM_CAMERA_LOG_LEVEL 3
#include "CameraCommon.h"
using namespace mozilla;
NS_IMPL_THREADSAFE_ISUPPORTS1(CameraPreview, CameraPreview)
class CameraPreviewListener : public MediaStreamListener
--- a/dom/camera/GonkCameraPreview.cpp
+++ b/dom/camera/GonkCameraPreview.cpp
@@ -28,17 +28,17 @@ using namespace mozilla;
void
GonkCameraPreview::ReceiveFrame(mozilla::layers::GraphicBufferLocked* aBuffer)
{
DOM_CAMERA_LOGI("%s:%d : this=%p\n", __func__, __LINE__, this);
if (!aBuffer)
return;
- Image::Format format = Image::GONK_IO_SURFACE;
+ ImageFormat format = ImageFormat::GONK_IO_SURFACE;
nsRefPtr<Image> image = mImageContainer->CreateImage(&format, 1);
GonkIOSurfaceImage* videoImage = static_cast<GonkIOSurfaceImage*>(image.get());
GonkIOSurfaceImage::Data data;
data.mGraphicBuffer = aBuffer;
data.mPicSize = gfxIntSize(mWidth, mHeight);
videoImage->SetData(data);
// AppendFrame() takes over image's reference
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -54,16 +54,17 @@ using mozilla::DefaultXDisplay;
#include "nsIAppShell.h"
#include "nsIDOMHTMLAppletElement.h"
#include "nsAttrName.h"
#include "nsIFocusManager.h"
#include "nsFocusManager.h"
#include "nsIDOMDragEvent.h"
#include "nsIScrollableFrame.h"
#include "nsIDocShell.h"
+#include "ImageContainer.h"
#include "nsContentCID.h"
#include "nsWidgetsCID.h"
static NS_DEFINE_CID(kWidgetCID, NS_CHILD_CID);
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
#ifdef XP_WIN
#include <wtypes.h>
@@ -172,17 +173,17 @@ nsPluginInstanceOwner::GetImageContainer
#if MOZ_WIDGET_ANDROID
// Right now we only draw with Gecko layers on Honeycomb and higher. See Paint()
// for what we do on other versions.
if (AndroidBridge::Bridge()->GetAPIVersion() < 11)
return NULL;
nsRefPtr<ImageContainer> container = LayerManager::CreateImageContainer();
- Image::Format format = Image::SHARED_TEXTURE;
+ ImageFormat format = ImageFormat::SHARED_TEXTURE;
nsRefPtr<Image> img = container->CreateImage(&format, 1);
SharedTextureImage::Data data;
data.mHandle = mInstance->CreateSharedHandle();
data.mShareType = mozilla::gl::TextureImage::ThreadShared;
data.mInverted = mInstance->Inverted();
gfxRect r = GetPluginRect();
@@ -205,17 +206,17 @@ nsPluginInstanceOwner::GetImageContainer
nsRefPtr<ImageContainer> container;
// Every call to nsIPluginInstance::GetImage() creates
// a new image. See nsIPluginInstance.idl.
mInstance->GetImageContainer(getter_AddRefs(container));
if (container) {
#ifdef XP_MACOSX
AutoLockImage autoLock(container);
Image* image = autoLock.GetImage();
- if (image && image->GetFormat() == Image::MAC_IO_SURFACE && mObjectFrame) {
+ if (image && image->GetFormat() == ImageFormat::MAC_IO_SURFACE && mObjectFrame) {
MacIOSurfaceImage *oglImage = static_cast<MacIOSurfaceImage*>(image);
NS_ADDREF_THIS();
oglImage->SetUpdateCallback(&DrawPlugin, this);
oglImage->SetDestroyCallback(&OnDestroyImage);
}
#endif
return container.forget();
}
@@ -1799,17 +1800,17 @@ void nsPluginInstanceOwner::GetVideos(ns
mInstance->GetVideos(aVideos);
}
already_AddRefed<ImageContainer> nsPluginInstanceOwner::GetImageContainerForVideo(nsNPAPIPluginInstance::VideoInfo* aVideoInfo)
{
nsRefPtr<ImageContainer> container = LayerManager::CreateImageContainer();
- Image::Format format = Image::SHARED_TEXTURE;
+ ImageFormat format = ImageFormat::SHARED_TEXTURE;
nsRefPtr<Image> img = container->CreateImage(&format, 1);
SharedTextureImage::Data data;
data.mHandle = mInstance->GLContext()->CreateSharedHandle(gl::TextureImage::ThreadShared, aVideoInfo->mSurfaceTexture, gl::GLContext::SurfaceTexture);
data.mShareType = mozilla::gl::TextureImage::ThreadShared;
data.mInverted = mInstance->Inverted();
data.mSize = gfxIntSize(aVideoInfo->mDimensions.width, aVideoInfo->mDimensions.height);
@@ -3711,17 +3712,17 @@ void nsPluginInstanceOwner::SetFrame(nsO
if (mObjectFrame) {
// We have an old frame.
// Drop image reference because the child may destroy the surface after we return.
nsRefPtr<ImageContainer> container = mObjectFrame->GetImageContainer();
if (container) {
#ifdef XP_MACOSX
AutoLockImage autoLock(container);
Image *image = autoLock.GetImage();
- if (image && (image->GetFormat() == Image::MAC_IO_SURFACE) && mObjectFrame) {
+ if (image && (image->GetFormat() == ImageFormat::MAC_IO_SURFACE) && mObjectFrame) {
// Undo what we did to the current image in SetCurrentImageInTransaction().
MacIOSurfaceImage *oglImage = static_cast<MacIOSurfaceImage*>(image);
oglImage->SetUpdateCallback(nullptr, nullptr);
oglImage->SetDestroyCallback(nullptr);
// If we have a current image here, its destructor hasn't yet been
// called, so OnDestroyImage() can't yet have been called. So we need
// to do ourselves what OnDestroyImage() would have done.
NS_RELEASE_THIS();
--- a/dom/plugins/ipc/PluginInstanceParent.cpp
+++ b/dom/plugins/ipc/PluginInstanceParent.cpp
@@ -20,16 +20,17 @@
#include "mozilla/StandardInteger.h" // for intptr_t
#ifdef MOZ_X11
#include "gfxXlibSurface.h"
#endif
#include "gfxContext.h"
#include "gfxColor.h"
#include "gfxUtils.h"
#include "nsNPAPIPluginInstance.h"
+#include "Layers.h"
#if defined(OS_WIN)
#include <windowsx.h>
#include "gfxWindowsPlatform.h"
#include "mozilla/plugins/PluginSurfaceParent.h"
// Plugin focus event for widget.
extern const PRUnichar* kOOPPPluginFocusEventId;
@@ -725,20 +726,20 @@ PluginInstanceParent::GetImageContainer(
}
if (!mFrontSurface && !ioSurface)
#else
if (!mFrontSurface)
#endif
return NS_ERROR_NOT_AVAILABLE;
- Image::Format format = Image::CAIRO_SURFACE;
+ ImageFormat format = ImageFormat::CAIRO_SURFACE;
#ifdef XP_MACOSX
if (ioSurface) {
- format = Image::MAC_IO_SURFACE;
+ format = ImageFormat::MAC_IO_SURFACE;
}
#endif
ImageContainer *container = GetImageContainer();
if (!container) {
return NS_ERROR_FAILURE;
}
@@ -752,30 +753,30 @@ PluginInstanceParent::GetImageContainer(
nsRefPtr<Image> image;
image = container->CreateImage(&format, 1);
if (!image) {
return NS_ERROR_FAILURE;
}
#ifdef XP_MACOSX
if (ioSurface) {
- NS_ASSERTION(image->GetFormat() == Image::MAC_IO_SURFACE, "Wrong format?");
+ NS_ASSERTION(image->GetFormat() == ImageFormat::MAC_IO_SURFACE, "Wrong format?");
MacIOSurfaceImage* ioImage = static_cast<MacIOSurfaceImage*>(image.get());
MacIOSurfaceImage::Data ioData;
ioData.mIOSurface = ioSurface;
ioImage->SetData(ioData);
container->SetCurrentImageInTransaction(ioImage);
NS_IF_ADDREF(container);
*aContainer = container;
return NS_OK;
}
#endif
- NS_ASSERTION(image->GetFormat() == Image::CAIRO_SURFACE, "Wrong format?");
+ NS_ASSERTION(image->GetFormat() == ImageFormat::CAIRO_SURFACE, "Wrong format?");
CairoImage* pluginImage = static_cast<CairoImage*>(image.get());
CairoImage::Data cairoData;
cairoData.mSurface = mFrontSurface;
cairoData.mSize = mFrontSurface->GetSize();
pluginImage->SetData(cairoData);
container->SetCurrentImageInTransaction(pluginImage);
--- a/dom/plugins/ipc/PluginInstanceParent.h
+++ b/dom/plugins/ipc/PluginInstanceParent.h
@@ -18,25 +18,29 @@
#endif
#include "npfunctions.h"
#include "nsAutoPtr.h"
#include "nsDataHashtable.h"
#include "nsHashKeys.h"
#include "nsRect.h"
#include "gfxASurface.h"
-#include "ImageLayers.h"
+
#ifdef MOZ_X11
class gfxXlibSurface;
#endif
#include "mozilla/unused.h"
#include "nsGUIEvent.h"
#include "mozilla/unused.h"
namespace mozilla {
+namespace layers {
+class ImageContainer;
+class CompositionNotifySink;
+}
namespace plugins {
class PBrowserStreamParent;
class PluginModuleParent;
class PluginInstanceParent : public PPluginInstanceParent
{
friend class PluginModuleParent;
new file mode 100644
--- /dev/null
+++ b/gfx/layers/ImageContainer.cpp
@@ -0,0 +1,552 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * 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 "mozilla/layers/ImageBridgeChild.h"
+#include "mozilla/layers/ImageContainerChild.h"
+
+#include "ImageContainer.h"
+#include "GonkIOSurfaceImage.h"
+#include "mozilla/ipc/Shmem.h"
+#include "mozilla/ipc/CrossProcessMutex.h"
+#include "SharedTextureImage.h"
+#include "gfxImageSurface.h"
+#include "gfxSharedImageSurface.h"
+#include "yuv_convert.h"
+#include "gfxUtils.h"
+
+#ifdef XP_MACOSX
+#include "mozilla/gfx/QuartzSupport.h"
+#endif
+
+#ifdef XP_WIN
+#include "gfxD2DSurface.h"
+#include "gfxWindowsPlatform.h"
+#include <d3d10_1.h>
+
+#include "d3d10/ImageLayerD3D10.h"
+#endif
+
+using namespace mozilla::ipc;
+using mozilla::gfx::DataSourceSurface;
+using mozilla::gfx::SourceSurface;
+
+
+namespace mozilla {
+namespace layers {
+
+already_AddRefed<Image>
+ImageFactory::CreateImage(const ImageFormat *aFormats,
+ PRUint32 aNumFormats,
+ const gfxIntSize &,
+ BufferRecycleBin *aRecycleBin)
+{
+ if (!aNumFormats) {
+ return nullptr;
+ }
+ nsRefPtr<Image> img;
+ if (FormatInList(aFormats, aNumFormats, ImageFormat::PLANAR_YCBCR)) {
+ img = new PlanarYCbCrImage(aRecycleBin);
+ } else if (FormatInList(aFormats, aNumFormats, ImageFormat::CAIRO_SURFACE)) {
+ img = new CairoImage();
+ } else if (FormatInList(aFormats, aNumFormats, ImageFormat::SHARED_TEXTURE)) {
+ img = new SharedTextureImage();
+#ifdef XP_MACOSX
+ } else if (FormatInList(aFormats, aNumFormats, ImageFormat::MAC_IO_SURFACE)) {
+ img = new MacIOSurfaceImage();
+#endif
+#ifdef MOZ_WIDGET_GONK
+ } else if (FormatInList(aFormats, aNumFormats, ImageFormat::GONK_IO_SURFACE)) {
+ img = new GonkIOSurfaceImage();
+#endif
+ }
+ return img.forget();
+}
+
+BufferRecycleBin::BufferRecycleBin()
+ : mLock("mozilla.layers.BufferRecycleBin.mLock")
+{
+}
+
+void
+BufferRecycleBin::RecycleBuffer(PRUint8* aBuffer, PRUint32 aSize)
+{
+ MutexAutoLock lock(mLock);
+
+ if (!mRecycledBuffers.IsEmpty() && aSize != mRecycledBufferSize) {
+ mRecycledBuffers.Clear();
+ }
+ mRecycledBufferSize = aSize;
+ mRecycledBuffers.AppendElement(aBuffer);
+}
+
+PRUint8*
+BufferRecycleBin::GetBuffer(PRUint32 aSize)
+{
+ MutexAutoLock lock(mLock);
+
+ if (mRecycledBuffers.IsEmpty() || mRecycledBufferSize != aSize)
+ return new PRUint8[aSize];
+
+ PRUint32 last = mRecycledBuffers.Length() - 1;
+ PRUint8* result = mRecycledBuffers[last].forget();
+ mRecycledBuffers.RemoveElementAt(last);
+ return result;
+}
+
+ImageContainer::ImageContainer(int flag)
+: mReentrantMonitor("ImageContainer.mReentrantMonitor"),
+ mPaintCount(0),
+ mPreviousImagePainted(false),
+ mImageFactory(new ImageFactory()),
+ mRecycleBin(new BufferRecycleBin()),
+ mRemoteData(nullptr),
+ mRemoteDataMutex(nullptr),
+ mCompositionNotifySink(nullptr),
+ mImageContainerChild(nullptr)
+{
+ if (flag == ENABLE_ASYNC && ImageBridgeChild::IsCreated()) {
+ mImageContainerChild =
+ ImageBridgeChild::GetSingleton()->CreateImageContainerChild();
+ }
+}
+
+ImageContainer::~ImageContainer()
+{
+ if (mImageContainerChild) {
+ mImageContainerChild->DispatchStop();
+ }
+}
+
+already_AddRefed<Image>
+ImageContainer::CreateImage(const ImageFormat *aFormats,
+ PRUint32 aNumFormats)
+{
+ ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+ return mImageFactory->CreateImage(aFormats, aNumFormats, mScaleHint, mRecycleBin);
+}
+
+void
+ImageContainer::SetCurrentImageInternal(Image *aImage)
+{
+ ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+
+ if (mRemoteData) {
+ NS_ASSERTION(mRemoteDataMutex, "Should have remote data mutex when having remote data!");
+ mRemoteDataMutex->Lock();
+ // This is important since it ensures we won't change the active image
+ // when we currently have a locked image that depends on mRemoteData.
+ }
+
+ mActiveImage = aImage;
+ CurrentImageChanged();
+
+ if (mRemoteData) {
+ mRemoteDataMutex->Unlock();
+ }
+}
+
+void
+ImageContainer::SetCurrentImage(Image *aImage)
+{
+ ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+
+ if (mImageContainerChild) {
+ if (aImage) {
+ mImageContainerChild->SendImageAsync(this, aImage);
+ } else {
+ mImageContainerChild->DispatchSetIdle();
+ }
+ }
+
+ SetCurrentImageInternal(aImage);
+}
+
+void
+ImageContainer::SetCurrentImageInTransaction(Image *aImage)
+{
+ NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
+ NS_ASSERTION(!mImageContainerChild, "Should use async image transfer with ImageBridge.");
+
+ SetCurrentImageInternal(aImage);
+}
+
+bool ImageContainer::IsAsync() const {
+ return mImageContainerChild != nullptr;
+}
+
+PRUint64 ImageContainer::GetAsyncContainerID() const
+{
+ NS_ASSERTION(IsAsync(),"Shared image ID is only relevant to async ImageContainers");
+ if (IsAsync()) {
+ return mImageContainerChild->GetID();
+ } else {
+ return 0; // zero is always an invalid SharedImageID
+ }
+}
+
+bool
+ImageContainer::HasCurrentImage()
+{
+ ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+
+ if (mRemoteData) {
+ CrossProcessMutexAutoLock autoLock(*mRemoteDataMutex);
+
+ EnsureActiveImage();
+
+ return !!mActiveImage.get();
+ }
+
+ return !!mActiveImage.get();
+}
+
+already_AddRefed<Image>
+ImageContainer::LockCurrentImage()
+{
+ ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+
+ if (mRemoteData) {
+ NS_ASSERTION(mRemoteDataMutex, "Should have remote data mutex when having remote data!");
+ mRemoteDataMutex->Lock();
+ }
+
+ EnsureActiveImage();
+
+ nsRefPtr<Image> retval = mActiveImage;
+ return retval.forget();
+}
+
+already_AddRefed<gfxASurface>
+ImageContainer::LockCurrentAsSurface(gfxIntSize *aSize, Image** aCurrentImage)
+{
+ ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+
+ if (mRemoteData) {
+ NS_ASSERTION(mRemoteDataMutex, "Should have remote data mutex when having remote data!");
+ mRemoteDataMutex->Lock();
+
+ EnsureActiveImage();
+
+ if (aCurrentImage) {
+ NS_IF_ADDREF(mActiveImage);
+ *aCurrentImage = mActiveImage.get();
+ }
+
+ if (!mActiveImage) {
+ return nullptr;
+ }
+
+ if (mActiveImage->GetFormat() == ImageFormat::REMOTE_IMAGE_BITMAP) {
+ nsRefPtr<gfxImageSurface> newSurf =
+ new gfxImageSurface(mRemoteData->mBitmap.mData, mRemoteData->mSize, mRemoteData->mBitmap.mStride,
+ mRemoteData->mFormat == RemoteImageData::BGRX32 ?
+ gfxASurface::ImageFormatARGB32 :
+ gfxASurface::ImageFormatRGB24);
+
+ *aSize = newSurf->GetSize();
+
+ return newSurf.forget();
+ }
+
+ *aSize = mActiveImage->GetSize();
+ return mActiveImage->GetAsSurface();
+ }
+
+ if (aCurrentImage) {
+ NS_IF_ADDREF(mActiveImage);
+ *aCurrentImage = mActiveImage.get();
+ }
+
+ if (!mActiveImage) {
+ return nullptr;
+ }
+
+ *aSize = mActiveImage->GetSize();
+ return mActiveImage->GetAsSurface();
+}
+
+void
+ImageContainer::UnlockCurrentImage()
+{
+ if (mRemoteData) {
+ NS_ASSERTION(mRemoteDataMutex, "Should have remote data mutex when having remote data!");
+ mRemoteDataMutex->Unlock();
+ }
+}
+
+already_AddRefed<gfxASurface>
+ImageContainer::GetCurrentAsSurface(gfxIntSize *aSize)
+{
+ ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+
+ if (mRemoteData) {
+ CrossProcessMutexAutoLock autoLock(*mRemoteDataMutex);
+ EnsureActiveImage();
+
+ if (!mActiveImage)
+ return nullptr;
+ *aSize = mRemoteData->mSize;
+ } else {
+ if (!mActiveImage)
+ return nullptr;
+ *aSize = mActiveImage->GetSize();
+ }
+ return mActiveImage->GetAsSurface();
+}
+
+gfxIntSize
+ImageContainer::GetCurrentSize()
+{
+ ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+
+ if (mRemoteData) {
+ CrossProcessMutexAutoLock autoLock(*mRemoteDataMutex);
+
+ // We don't need to ensure we have an active image here, as we need to
+ // be in the mutex anyway, and this is easiest to return from there.
+ return mRemoteData->mSize;
+ }
+
+ if (!mActiveImage) {
+ return gfxIntSize(0,0);
+ }
+
+ return mActiveImage->GetSize();
+}
+
+void
+ImageContainer::SetRemoteImageData(RemoteImageData *aData, CrossProcessMutex *aMutex)
+{
+ ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+
+ NS_ASSERTION(!mActiveImage || !aData, "No active image expected when SetRemoteImageData is called with non-NULL aData.");
+ NS_ASSERTION(!mRemoteData || !aData, "No remote data expected when SetRemoteImageData is called with non-NULL aData.");
+
+ mRemoteData = aData;
+
+ if (aData) {
+ memset(aData, 0, sizeof(RemoteImageData));
+ } else {
+ mActiveImage = nullptr;
+ }
+
+ mRemoteDataMutex = aMutex;
+}
+
+void
+ImageContainer::EnsureActiveImage()
+{
+ if (mRemoteData) {
+ if (mRemoteData->mWasUpdated) {
+ mActiveImage = nullptr;
+ }
+
+ if (mRemoteData->mType == RemoteImageData::RAW_BITMAP &&
+ mRemoteData->mBitmap.mData && !mActiveImage) {
+ nsRefPtr<RemoteBitmapImage> newImg = new RemoteBitmapImage();
+
+ newImg->mFormat = mRemoteData->mFormat;
+ newImg->mData = mRemoteData->mBitmap.mData;
+ newImg->mSize = mRemoteData->mSize;
+ newImg->mStride = mRemoteData->mBitmap.mStride;
+ mRemoteData->mWasUpdated = false;
+
+ mActiveImage = newImg;
+ }
+#ifdef XP_WIN
+ else if (mRemoteData->mType == RemoteImageData::DXGI_TEXTURE_HANDLE &&
+ mRemoteData->mTextureHandle && !mActiveImage) {
+ nsRefPtr<RemoteDXGITextureImage> newImg = new RemoteDXGITextureImage();
+ newImg->mSize = mRemoteData->mSize;
+ newImg->mHandle = mRemoteData->mTextureHandle;
+ newImg->mFormat = mRemoteData->mFormat;
+ mRemoteData->mWasUpdated = false;
+
+ mActiveImage = newImg;
+ }
+#endif
+ }
+}
+
+
+PlanarYCbCrImage::PlanarYCbCrImage(BufferRecycleBin *aRecycleBin)
+ : Image(nullptr, PLANAR_YCBCR)
+ , mBufferSize(0)
+ , mRecycleBin(aRecycleBin)
+{
+}
+
+PlanarYCbCrImage::~PlanarYCbCrImage()
+{
+ if (mBuffer) {
+ mRecycleBin->RecycleBuffer(mBuffer.forget(), mBufferSize);
+ }
+}
+
+PRUint8*
+PlanarYCbCrImage::AllocateBuffer(PRUint32 aSize)
+{
+ return mRecycleBin->GetBuffer(aSize);
+}
+
+static void
+CopyPlane(PRUint8 *aDst, PRUint8 *aSrc,
+ const gfxIntSize &aSize, PRInt32 aStride,
+ PRInt32 aOffset, PRInt32 aSkip)
+{
+ if (!aOffset && !aSkip) {
+ // Fast path: planar input.
+ memcpy(aDst, aSrc, aSize.height * aStride);
+ } else {
+ PRInt32 height = aSize.height;
+ PRInt32 width = aSize.width;
+ for (int y = 0; y < height; ++y) {
+ PRUint8 *src = aSrc + aOffset;
+ PRUint8 *dst = aDst;
+ if (!aSkip) {
+ // Fast path: offset only, no per-pixel skip.
+ memcpy(dst, src, width);
+ } else {
+ // Slow path
+ for (int x = 0; x < width; ++x) {
+ *dst++ = *src++;
+ src += aSkip;
+ }
+ }
+ aSrc += aStride;
+ aDst += aStride;
+ }
+ }
+}
+
+void
+PlanarYCbCrImage::CopyData(const Data& aData,
+ PRInt32 aYOffset, PRInt32 aYSkip,
+ PRInt32 aCbOffset, PRInt32 aCbSkip,
+ PRInt32 aCrOffset, PRInt32 aCrSkip)
+{
+ mData = aData;
+
+ // update buffer size
+ mBufferSize = mData.mCbCrStride * mData.mCbCrSize.height * 2 +
+ mData.mYStride * mData.mYSize.height;
+
+ // get new buffer
+ mBuffer = AllocateBuffer(mBufferSize);
+ if (!mBuffer)
+ return;
+
+ mData.mYChannel = mBuffer;
+ mData.mCbChannel = mData.mYChannel + mData.mYStride * mData.mYSize.height;
+ mData.mCrChannel = mData.mCbChannel + mData.mCbCrStride * mData.mCbCrSize.height;
+
+ CopyPlane(mData.mYChannel, aData.mYChannel,
+ mData.mYSize, mData.mYStride,
+ aYOffset, aYSkip);
+ CopyPlane(mData.mCbChannel, aData.mCbChannel,
+ mData.mCbCrSize, mData.mCbCrStride,
+ aCbOffset, aCbSkip);
+ CopyPlane(mData.mCrChannel, aData.mCrChannel,
+ mData.mCbCrSize, mData.mCbCrStride,
+ aCrOffset, aCrSkip);
+
+ mSize = aData.mPicSize;
+}
+
+void
+PlanarYCbCrImage::SetData(const Data &aData)
+{
+ CopyData(aData);
+}
+
+already_AddRefed<gfxASurface>
+PlanarYCbCrImage::GetAsSurface()
+{
+ if (mSurface) {
+ nsRefPtr<gfxASurface> result = mSurface.get();
+ return result.forget();
+ }
+
+ gfxASurface::gfxImageFormat format = GetOffscreenFormat();
+
+ gfxIntSize size(mSize);
+ gfxUtils::GetYCbCrToRGBDestFormatAndSize(mData, format, size);
+ if (size.width > PlanarYCbCrImage::MAX_DIMENSION ||
+ size.height > PlanarYCbCrImage::MAX_DIMENSION) {
+ NS_ERROR("Illegal image dest width or height");
+ return nullptr;
+ }
+
+ nsRefPtr<gfxImageSurface> imageSurface =
+ new gfxImageSurface(mSize, format);
+
+ gfxUtils::ConvertYCbCrToRGB(mData, format, mSize,
+ imageSurface->Data(),
+ imageSurface->Stride());
+
+ mSurface = imageSurface;
+
+ return imageSurface.forget().get();
+}
+
+#ifdef XP_MACOSX
+void
+MacIOSurfaceImage::SetData(const Data& aData)
+{
+ mIOSurface = MacIOSurface::LookupSurface(aData.mIOSurface->GetIOSurfaceID());
+ mSize = gfxIntSize(mIOSurface->GetWidth(), mIOSurface->GetHeight());
+}
+
+already_AddRefed<gfxASurface>
+MacIOSurfaceImage::GetAsSurface()
+{
+ mIOSurface->Lock();
+ size_t bytesPerRow = mIOSurface->GetBytesPerRow();
+ size_t ioWidth = mIOSurface->GetWidth();
+ size_t ioHeight = mIOSurface->GetHeight();
+
+ unsigned char* ioData = (unsigned char*)mIOSurface->GetBaseAddress();
+
+ nsRefPtr<gfxImageSurface> imgSurface =
+ new gfxImageSurface(gfxIntSize(ioWidth, ioHeight), gfxASurface::ImageFormatARGB32);
+
+ for (int i = 0; i < ioHeight; i++) {
+ memcpy(imgSurface->Data() + i * imgSurface->Stride(),
+ ioData + i * bytesPerRow, ioWidth * 4);
+ }
+
+ mIOSurface->Unlock();
+
+ return imgSurface.forget();
+}
+
+void
+MacIOSurfaceImage::Update(ImageContainer* aContainer)
+{
+ if (mUpdateCallback) {
+ mUpdateCallback(aContainer, mPluginInstanceOwner);
+ }
+}
+#endif
+
+already_AddRefed<gfxASurface>
+RemoteBitmapImage::GetAsSurface()
+{
+ nsRefPtr<gfxImageSurface> newSurf =
+ new gfxImageSurface(mSize,
+ mFormat == RemoteImageData::BGRX32 ? gfxASurface::ImageFormatRGB24 : gfxASurface::ImageFormatARGB32);
+
+ for (int y = 0; y < mSize.height; y++) {
+ memcpy(newSurf->Data() + newSurf->Stride() * y,
+ mData + mStride * y,
+ mSize.width * 4);
+ }
+
+ return newSurf.forget();
+}
+
+} // namespace
+} // namespace
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/gfx/layers/ImageContainer.h
@@ -0,0 +1,830 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * 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 GFX_IMAGECONTAINER_H
+#define GFX_IMAGECONTAINER_H
+
+#include "mozilla/Mutex.h"
+#include "mozilla/ReentrantMonitor.h"
+#include "gfxASurface.h" // for gfxImageFormat
+#include "LayersTypes.h" // for LayersBackend
+#include "mozilla/TimeStamp.h"
+#include "ImageTypes.h"
+
+#ifdef XP_WIN
+struct ID3D10Texture2D;
+struct ID3D10Device;
+struct ID3D10ShaderResourceView;
+#endif
+
+#ifdef XP_MACOSX
+#include "mozilla/gfx/MacIOSurface.h"
+#endif
+
+#ifdef MOZ_WIDGET_GONK
+# include <ui/GraphicBuffer.h>
+#endif
+
+typedef void* HANDLE;
+
+namespace mozilla {
+
+class CrossProcessMutex;
+namespace ipc {
+class Shmem;
+}
+
+namespace layers {
+
+class ImageContainerChild;
+
+struct ImageBackendData
+{
+ virtual ~ImageBackendData() {}
+
+protected:
+ ImageBackendData() {}
+};
+
+/**
+ * A class representing a buffer of pixel data. The data can be in one
+ * of various formats including YCbCr.
+ *
+ * Create an image using an ImageContainer. Fill the image with data, and
+ * then call ImageContainer::SetImage to display it. An image must not be
+ * modified after calling SetImage. Image implementations do not need to
+ * perform locking; when filling an Image, the Image client is responsible
+ * for ensuring only one thread accesses the Image at a time, and after
+ * SetImage the image is immutable.
+ *
+ * When resampling an Image, only pixels within the buffer should be
+ * sampled. For example, cairo images should be sampled in EXTEND_PAD mode.
+ */
+class THEBES_API Image {
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Image)
+
+public:
+ virtual ~Image() {}
+
+
+ ImageFormat GetFormat() { return mFormat; }
+ void* GetImplData() { return mImplData; }
+
+ virtual already_AddRefed<gfxASurface> GetAsSurface() = 0;
+ virtual gfxIntSize GetSize() = 0;
+
+ ImageBackendData* GetBackendData(LayersBackend aBackend)
+ { return mBackendData[aBackend]; }
+ void SetBackendData(LayersBackend aBackend, ImageBackendData* aData)
+ { mBackendData[aBackend] = aData; }
+
+protected:
+ Image(void* aImplData, ImageFormat aFormat) :
+ mImplData(aImplData),
+ mFormat(aFormat)
+ {}
+
+ nsAutoPtr<ImageBackendData> mBackendData[mozilla::layers::LAYERS_LAST];
+
+ void* mImplData;
+ ImageFormat mFormat;
+};
+
+/**
+ * A RecycleBin is owned by an ImageContainer. We store buffers in it that we
+ * want to recycle from one image to the next.It's a separate object from
+ * ImageContainer because images need to store a strong ref to their RecycleBin
+ * and we must avoid creating a reference loop between an ImageContainer and
+ * its active image.
+ */
+class BufferRecycleBin {
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RecycleBin)
+
+ //typedef mozilla::gl::GLContext GLContext;
+
+public:
+ BufferRecycleBin();
+
+ void RecycleBuffer(PRUint8* aBuffer, PRUint32 aSize);
+ // Returns a recycled buffer of the right size, or allocates a new buffer.
+ PRUint8* GetBuffer(PRUint32 aSize);
+
+private:
+ typedef mozilla::Mutex Mutex;
+
+ // This protects mRecycledBuffers, mRecycledBufferSize, mRecycledTextures
+ // and mRecycledTextureSizes
+ Mutex mLock;
+
+ // We should probably do something to prune this list on a timer so we don't
+ // eat excess memory while video is paused...
+ nsTArray<nsAutoArrayPtr<PRUint8> > mRecycledBuffers;
+ // This is only valid if mRecycledBuffers is non-empty
+ PRUint32 mRecycledBufferSize;
+};
+
+/**
+ * Returns true if aFormat is in the given format array.
+ */
+static inline bool
+FormatInList(const ImageFormat* aFormats, PRUint32 aNumFormats,
+ ImageFormat aFormat)
+{
+ for (PRUint32 i = 0; i < aNumFormats; ++i) {
+ if (aFormats[i] == aFormat) {
+ return true;
+ }
+ }
+ return false;
+}
+
+class CompositionNotifySink
+{
+public:
+ virtual void DidComposite() = 0;
+ virtual ~CompositionNotifySink() {}
+};
+
+/**
+ * A class that manages Image creation for a LayerManager. The only reason
+ * we need a separate class here is that LayerMananers aren't threadsafe
+ * (because layers can only be used on the main thread) and we want to
+ * be able to create images from any thread, to facilitate video playback
+ * without involving the main thread, for example.
+ * Different layer managers can implement child classes of this making it
+ * possible to create layer manager specific images.
+ * This class is not meant to be used directly but rather can be set on an
+ * image container. This is usually done by the layer system internally and
+ * not explicitly by users. For PlanarYCbCr or Cairo images the default
+ * implementation will creates images whose data lives in system memory, for
+ * MacIOSurfaces the default implementation will be a simple MacIOSurface
+ * wrapper.
+ */
+
+class THEBES_API ImageFactory
+{
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ImageFactory)
+protected:
+ friend class ImageContainer;
+
+ ImageFactory() {}
+ virtual ~ImageFactory() {}
+
+ virtual already_AddRefed<Image> CreateImage(const ImageFormat* aFormats,
+ PRUint32 aNumFormats,
+ const gfxIntSize &aScaleHint,
+ BufferRecycleBin *aRecycleBin);
+
+};
+
+/**
+ * This struct is used to store RemoteImages, it is meant to be able to live in
+ * shared memory. Therefor it should not contain a vtable pointer. Remote
+ * users can manipulate the data in this structure to specify what image is to
+ * be drawn by the container. When accessing this data users should make sure
+ * the mutex synchronizing access to the structure is held!
+ */
+struct RemoteImageData {
+ enum Type {
+ /**
+ * This is a format that uses raw bitmap data.
+ */
+ RAW_BITMAP,
+
+ /**
+ * This is a format that uses a pointer to a texture do draw directly
+ * from a shared texture. Any process may have created this texture handle,
+ * the process creating the texture handle is responsible for managing it's
+ * lifetime by managing the lifetime of the first D3D texture object this
+ * handle was created for. It must also ensure the handle is not set
+ * current anywhere when the last reference to this object is released.
+ */
+ DXGI_TEXTURE_HANDLE
+ };
+ /* These formats describe the format in the memory byte-order */
+ enum Format {
+ /* 8 bits per channel */
+ BGRA32,
+ /* 8 bits per channel, alpha channel is ignored */
+ BGRX32
+ };
+
+ // This should be set to true if a change was made so that the ImageContainer
+ // knows to throw out any cached RemoteImage objects.
+ bool mWasUpdated;
+ Type mType;
+ Format mFormat;
+ gfxIntSize mSize;
+ union {
+ struct {
+ /* This pointer is set by a remote process, however it will be set to
+ * the container process' address the memory of the raw bitmap resides
+ * at.
+ */
+ unsigned char *mData;
+ int mStride;
+ } mBitmap;
+#ifdef XP_WIN
+ HANDLE mTextureHandle;
+#endif
+ };
+};
+
+/**
+ * A class that manages Images for an ImageLayer. The only reason
+ * we need a separate class here is that ImageLayers aren't threadsafe
+ * (because layers can only be used on the main thread) and we want to
+ * be able to set the current Image from any thread, to facilitate
+ * video playback without involving the main thread, for example.
+ *
+ * An ImageContainer can operate in one of three modes:
+ * 1) Normal. Triggered by constructing the ImageContainer with
+ * DISABLE_ASYNC or when compositing is happening on the main thread.
+ * SetCurrentImage changes ImageContainer state but nothing is sent to the
+ * compositor until the next layer transaction.
+ * 2) Asynchronous. Initiated by constructing the ImageContainer with
+ * ENABLE_ASYNC when compositing is happening on the main thread.
+ * SetCurrentImage sends a message through the ImageBridge to the compositor
+ * thread to update the image, without going through the main thread or
+ * a layer transaction.
+ * 3) Remote. Initiated by calling SetRemoteImageData on the ImageContainer
+ * before any other activity.
+ * The ImageContainer uses a shared memory block containing a cross-process mutex
+ * to communicate with the compositor thread. SetCurrentImage synchronously
+ * updates the shared state to point to the new image and the old image
+ * is immediately released (not true in Normal or Asynchronous modes).
+ */
+class THEBES_API ImageContainer {
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ImageContainer)
+public:
+
+ enum { DISABLE_ASYNC = 0x0, ENABLE_ASYNC = 0x01 };
+
+ ImageContainer(int flag = 0);
+
+ ~ImageContainer();
+
+ /**
+ * Create an Image in one of the given formats.
+ * Picks the "best" format from the list and creates an Image of that
+ * format.
+ * Returns null if this backend does not support any of the formats.
+ * Can be called on any thread. This method takes mReentrantMonitor
+ * when accessing thread-shared state.
+ */
+ already_AddRefed<Image> CreateImage(const ImageFormat* aFormats,
+ PRUint32 aNumFormats);
+
+ /**
+ * Set an Image as the current image to display. The Image must have
+ * been created by this ImageContainer.
+ * Can be called on any thread. This method takes mReentrantMonitor
+ * when accessing thread-shared state.
+ * aImage can be null. While it's null, nothing will be painted.
+ *
+ * The Image data must not be modified after this method is called!
+ * Note that this must not be called if ENABLE_ASYNC has not been set.
+ *
+ * Implementations must call CurrentImageChanged() while holding
+ * mReentrantMonitor.
+ *
+ * If this ImageContainer has an ImageContainerChild for async video:
+ * Schelude a task to send the image to the compositor using the
+ * PImageBridge protcol without using the main thread.
+ */
+ void SetCurrentImage(Image* aImage);
+
+ /**
+ * Set an Image as the current image to display. The Image must have
+ * been created by this ImageContainer.
+ * Must be called on the main thread, within a layers transaction.
+ *
+ * This method takes mReentrantMonitor
+ * when accessing thread-shared state.
+ * aImage can be null. While it's null, nothing will be painted.
+ *
+ * The Image data must not be modified after this method is called!
+ * Note that this must not be called if ENABLE_ASYNC been set.
+ *
+ * Implementations must call CurrentImageChanged() while holding
+ * mReentrantMonitor.
+ */
+ void SetCurrentImageInTransaction(Image* aImage);
+
+ /**
+ * Returns true if this ImageContainer uses the ImageBridge IPDL protocol.
+ *
+ * Can be called from any thread.
+ */
+ bool IsAsync() const;
+
+ /**
+ * If this ImageContainer uses ImageBridge, returns the ID associated to
+ * this container, for use in the ImageBridge protocol.
+ * Returns 0 if this ImageContainer does not use ImageBridge. Note that
+ * 0 is always an invalid ID for asynchronous image containers.
+ *
+ * Can be called from ay thread.
+ */
+ PRUint64 GetAsyncContainerID() const;
+
+ /**
+ * Returns if the container currently has an image.
+ * Can be called on any thread. This method takes mReentrantMonitor
+ * when accessing thread-shared state.
+ */
+ bool HasCurrentImage();
+
+ /**
+ * Lock the current Image.
+ * This has to add a reference since otherwise there are race conditions
+ * where the current image is destroyed before the caller can add
+ * a reference. This lock strictly guarantees the underlying image remains
+ * valid, it does not mean the current image cannot change.
+ * Can be called on any thread. This method will lock the cross-process
+ * mutex to ensure remote processes cannot alter underlying data. This call
+ * -must- be balanced by a call to UnlockCurrentImage and users should avoid
+ * holding the image locked for a long time.
+ */
+ already_AddRefed<Image> LockCurrentImage();
+
+ /**
+ * This call unlocks the image. For remote images releasing the cross-process
+ * mutex.
+ */
+ void UnlockCurrentImage();
+
+ /**
+ * Get the current image as a gfxASurface. This is useful for fallback
+ * rendering.
+ * This can only be called from the main thread, since cairo objects
+ * can only be used from the main thread.
+ * This is defined here and not on Image because it's possible (likely)
+ * that some backends will make an Image "ready to draw" only when it
+ * becomes the current image for an image container.
+ * Returns null if there is no current image.
+ * Returns the size in aSize.
+ * The returned surface will never be modified. The caller must not
+ * modify it.
+ * Can be called on any thread. This method takes mReentrantMonitor
+ * when accessing thread-shared state.
+ * If the current image is a remote image, that is, if it is an image that
+ * may be shared accross processes, calling this function will make
+ * a copy of the image data while holding the mRemoteDataMutex. If possible,
+ * the lock methods should be used to avoid the copy, however this should be
+ * avoided if the surface is required for a long period of time.
+ */
+ already_AddRefed<gfxASurface> GetCurrentAsSurface(gfxIntSize* aSizeResult);
+
+ /**
+ * This is similar to GetCurrentAsSurface, however this does not make a copy
+ * of the image data and requires the user to call UnlockCurrentImage when
+ * done with the image data. Once UnlockCurrentImage has been called the
+ * surface returned by this function is no longer valid! This works for any
+ * type of image. Optionally a pointer can be passed to receive the current
+ * image.
+ */
+ already_AddRefed<gfxASurface> LockCurrentAsSurface(gfxIntSize* aSizeResult,
+ Image** aCurrentImage = nullptr);
+
+ /**
+ * Returns the size of the image in pixels.
+ * Can be called on any thread. This method takes mReentrantMonitor when accessing
+ * thread-shared state.
+ */
+ gfxIntSize GetCurrentSize();
+
+ /**
+ * Sets a size that the image is expected to be rendered at.
+ * This is a hint for image backends to optimize scaling.
+ * Default implementation in this class is to ignore the hint.
+ * Can be called on any thread. This method takes mReentrantMonitor
+ * when accessing thread-shared state.
+ */
+ void SetScaleHint(const gfxIntSize& aScaleHint)
+ { mScaleHint = aScaleHint; }
+
+ void SetImageFactory(ImageFactory *aFactory)
+ {
+ ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+ mImageFactory = aFactory ? aFactory : new ImageFactory();
+ }
+
+ /**
+ * Returns the time at which the currently contained image was first
+ * painted. This is reset every time a new image is set as the current
+ * image. Note this may return a null timestamp if the current image
+ * has not yet been painted. Can be called from any thread.
+ */
+ TimeStamp GetPaintTime() {
+ ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+ return mPaintTime;
+ }
+
+ /**
+ * Returns the number of images which have been contained in this container
+ * and painted at least once. Can be called from any thread.
+ */
+ PRUint32 GetPaintCount() {
+ ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+ return mPaintCount;
+ }
+
+ /**
+ * Increments mPaintCount if this is the first time aPainted has been
+ * painted, and sets mPaintTime if the painted image is the current image.
+ * current image. Can be called from any thread.
+ */
+ void NotifyPaintedImage(Image* aPainted) {
+ ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+
+ nsRefPtr<Image> current = mActiveImage;
+ if (aPainted == current) {
+ if (mPaintTime.IsNull()) {
+ mPaintTime = TimeStamp::Now();
+ mPaintCount++;
+ }
+ } else if (!mPreviousImagePainted) {
+ // While we were painting this image, the current image changed. We
+ // still must count it as painted, but can't set mPaintTime, since we're
+ // no longer the current image.
+ mPaintCount++;
+ mPreviousImagePainted = true;
+ }
+
+ if (mCompositionNotifySink) {
+ mCompositionNotifySink->DidComposite();
+ }
+ }
+
+ void SetCompositionNotifySink(CompositionNotifySink *aSink) {
+ mCompositionNotifySink = aSink;
+ }
+
+ /**
+ * This function is called to tell the ImageContainer where the
+ * (cross-process) segment lives where the shared data about possible
+ * remote images are stored. In addition to this a CrossProcessMutex object
+ * is passed telling the container how to synchronize access to this data.
+ * NOTE: This should be called during setup of the container and not after
+ * usage has started.
+ */
+ void SetRemoteImageData(RemoteImageData *aRemoteData,
+ CrossProcessMutex *aRemoteDataMutex);
+ /**
+ * This can be used to check if the container has RemoteData set.
+ */
+ RemoteImageData *GetRemoteImageData() { return mRemoteData; }
+
+protected:
+ typedef mozilla::ReentrantMonitor ReentrantMonitor;
+
+ void SetCurrentImageInternal(Image* aImage);
+
+ // This is called to ensure we have an active image, this may not be true
+ // when we're storing image information in a RemoteImageData structure.
+ // NOTE: If we have remote data mRemoteDataMutex should be locked when
+ // calling this function!
+ void EnsureActiveImage();
+
+ // ReentrantMonitor to protect thread safe access to the "current
+ // image", and any other state which is shared between threads.
+ ReentrantMonitor mReentrantMonitor;
+
+ // Performs necessary housekeeping to ensure the painted frame statistics
+ // are accurate. Must be called by SetCurrentImage() implementations with
+ // mReentrantMonitor held.
+ void CurrentImageChanged() {
+ mReentrantMonitor.AssertCurrentThreadIn();
+ mPreviousImagePainted = !mPaintTime.IsNull();
+ mPaintTime = TimeStamp();
+ }
+
+ nsRefPtr<Image> mActiveImage;
+
+ // Number of contained images that have been painted at least once. It's up
+ // to the ImageContainer implementation to ensure accesses to this are
+ // threadsafe.
+ PRUint32 mPaintCount;
+
+ // Time stamp at which the current image was first painted. It's up to the
+ // ImageContainer implementation to ensure accesses to this are threadsafe.
+ TimeStamp mPaintTime;
+
+ // Denotes whether the previous image was painted.
+ bool mPreviousImagePainted;
+
+ // This is the image factory used by this container, layer managers using
+ // this container can set an alternative image factory that will be used to
+ // create images for this container.
+ nsRefPtr<ImageFactory> mImageFactory;
+
+ gfxIntSize mScaleHint;
+
+ nsRefPtr<BufferRecycleBin> mRecycleBin;
+
+ // This contains the remote image data for this container, if this is NULL
+ // that means the container has no other process that may control its active
+ // image.
+ RemoteImageData *mRemoteData;
+
+ // This cross-process mutex is used to synchronise access to mRemoteData.
+ // When this mutex is held, we will always be inside the mReentrantMonitor
+ // however the same is not true vice versa.
+ CrossProcessMutex *mRemoteDataMutex;
+
+ CompositionNotifySink *mCompositionNotifySink;
+
+ // This member points to an ImageContainerChild if this ImageContainer was
+ // sucessfully created with ENABLE_ASYNC, or points to null otherwise.
+ // 'unsuccessful' in this case only means that the ImageContainerChild could not
+ // be created, most likely because off-main-thread compositing is not enabled.
+ // In this case the ImageContainer is perfectly usable, but it will forward
+ // frames to the compositor through transactions in the main thread rather than
+ // asynchronusly using the ImageBridge IPDL protocol.
+ nsRefPtr<ImageContainerChild> mImageContainerChild;
+};
+
+class AutoLockImage
+{
+public:
+ AutoLockImage(ImageContainer *aContainer) : mContainer(aContainer) { mImage = mContainer->LockCurrentImage(); }
+ AutoLockImage(ImageContainer *aContainer, gfxASurface **aSurface) : mContainer(aContainer) {
+ *aSurface = mContainer->LockCurrentAsSurface(&mSize, getter_AddRefs(mImage)).get();
+ }
+ ~AutoLockImage() { if (mContainer) { mContainer->UnlockCurrentImage(); } }
+
+ Image* GetImage() { return mImage; }
+ const gfxIntSize &GetSize() { return mSize; }
+
+ void Unlock() {
+ if (mContainer) {
+ mImage = nullptr;
+ mContainer->UnlockCurrentImage();
+ mContainer = nullptr;
+ }
+ }
+
+ /** Things get a little tricky here, because our underlying image can -still-
+ * change, and OS X requires a complicated callback mechanism to update this
+ * we need to support staying the lock and getting the new image in a proper
+ * way. This method makes any images retrieved with GetImage invalid!
+ */
+ void Refresh() {
+ if (mContainer) {
+ mContainer->UnlockCurrentImage();
+ mImage = mContainer->LockCurrentImage();
+ }
+ }
+
+private:
+ ImageContainer *mContainer;
+ nsRefPtr<Image> mImage;
+ gfxIntSize mSize;
+};
+
+/****** Image subtypes for the different formats ******/
+
+/**
+ * We assume that the image data is in the REC 470M color space (see
+ * Theora specification, section 4.3.1).
+ *
+ * The YCbCr format can be:
+ *
+ * 4:4:4 - CbCr width/height are the same as Y.
+ * 4:2:2 - CbCr width is half that of Y. Height is the same.
+ * 4:2:0 - CbCr width and height is half that of Y.
+ *
+ * The color format is detected based on the height/width ratios
+ * defined above.
+ *
+ * The Image that is rendered is the picture region defined by
+ * mPicX, mPicY and mPicSize. The size of the rendered image is
+ * mPicSize, not mYSize or mCbCrSize.
+ */
+class THEBES_API PlanarYCbCrImage : public Image {
+public:
+ struct Data {
+ // Luminance buffer
+ PRUint8* mYChannel;
+ PRInt32 mYStride;
+ gfxIntSize mYSize;
+ // Chroma buffers
+ PRUint8* mCbChannel;
+ PRUint8* mCrChannel;
+ PRInt32 mCbCrStride;
+ gfxIntSize mCbCrSize;
+ // Picture region
+ PRUint32 mPicX;
+ PRUint32 mPicY;
+ gfxIntSize mPicSize;
+ StereoMode mStereoMode;
+
+ nsIntRect GetPictureRect() const {
+ return nsIntRect(mPicX, mPicY,
+ mPicSize.width,
+ mPicSize.height);
+ }
+ };
+
+ enum {
+ MAX_DIMENSION = 16384
+ };
+
+ ~PlanarYCbCrImage();
+
+ /**
+ * This makes a copy of the data buffers, in order to support functioning
+ * in all different layer managers.
+ */
+ virtual void SetData(const Data& aData);
+
+ /**
+ * Ask this Image to not convert YUV to RGB during SetData, and make
+ * the original data available through GetData. This is optional,
+ * and not all PlanarYCbCrImages will support it.
+ */
+ virtual void SetDelayedConversion(bool aDelayed) { }
+
+ /**
+ * Grab the original YUV data. This is optional.
+ */
+ virtual const Data* GetData() { return &mData; }
+
+ /**
+ * Make a copy of the YCbCr data into local storage.
+ *
+ * @param aData Input image data.
+ * @param aYOffset Pixels to skip between lines in the Y plane.
+ * @param aYSkip Pixels to skip between pixels in the Y plane.
+ * @param aCbOffset Pixels to skip between lines in the Cb plane.
+ * @param aCbSkip Pixels to skip between pixels in the Cb plane.
+ * @param aCrOffset Pixels to skip between lines in the Cr plane.
+ * @param aCrSkip Pixels to skip between pixels in the Cr plane.
+ */
+ void CopyData(const Data& aData,
+ PRInt32 aYOffset = 0, PRInt32 aYSkip = 0,
+ PRInt32 aCbOffset = 0, PRInt32 aCbSkip = 0,
+ PRInt32 aCrOffset = 0, PRInt32 aCrSkip = 0);
+
+ /**
+ * Return a buffer to store image data in.
+ * The default implementation returns memory that can
+ * be freed wit delete[]
+ */
+ virtual PRUint8* AllocateBuffer(PRUint32 aSize);
+
+ /**
+ * Return the number of bytes of heap memory used to store this image.
+ */
+ virtual PRUint32 GetDataSize() { return mBufferSize; }
+
+ already_AddRefed<gfxASurface> GetAsSurface();
+
+ virtual gfxIntSize GetSize() { return mSize; }
+
+ void SetOffscreenFormat(gfxASurface::gfxImageFormat aFormat) { mOffscreenFormat = aFormat; }
+ gfxASurface::gfxImageFormat GetOffscreenFormat() { return mOffscreenFormat; }
+
+ // XXX - not easy to protect these sadly.
+ nsAutoArrayPtr<PRUint8> mBuffer;
+ PRUint32 mBufferSize;
+ Data mData;
+ gfxIntSize mSize;
+ gfxASurface::gfxImageFormat mOffscreenFormat;
+ nsCountedRef<nsMainThreadSurfaceRef> mSurface;
+ nsRefPtr<BufferRecycleBin> mRecycleBin;
+
+ PlanarYCbCrImage(BufferRecycleBin *aRecycleBin);
+};
+
+/**
+ * Currently, the data in a CairoImage surface is treated as being in the
+ * device output color space. This class is very simple as all backends
+ * have to know about how to deal with drawing a cairo image.
+ */
+class THEBES_API CairoImage : public Image {
+public:
+ struct Data {
+ gfxASurface* mSurface;
+ gfxIntSize mSize;
+ };
+
+ /**
+ * This can only be called on the main thread. It may add a reference
+ * to the surface (which will eventually be released on the main thread).
+ * The surface must not be modified after this call!!!
+ */
+ void SetData(const Data& aData)
+ {
+ mSurface = aData.mSurface;
+ mSize = aData.mSize;
+ }
+
+
+ virtual already_AddRefed<gfxASurface> GetAsSurface()
+ {
+ NS_ASSERTION(NS_IsMainThread(), "Must be main thread");
+ nsRefPtr<gfxASurface> surface = mSurface.get();
+ return surface.forget();
+ }
+
+ gfxIntSize GetSize() { return mSize; }
+
+ CairoImage() : Image(NULL, CAIRO_SURFACE) {}
+
+ nsCountedRef<nsMainThreadSurfaceRef> mSurface;
+ gfxIntSize mSize;
+};
+
+#ifdef XP_MACOSX
+class THEBES_API MacIOSurfaceImage : public Image {
+public:
+ struct Data {
+ MacIOSurface* mIOSurface;
+ };
+
+ MacIOSurfaceImage()
+ : Image(NULL, MAC_IO_SURFACE)
+ , mSize(0, 0)
+ , mPluginInstanceOwner(NULL)
+ , mUpdateCallback(NULL)
+ , mDestroyCallback(NULL)
+ {}
+
+ virtual ~MacIOSurfaceImage()
+ {
+ if (mDestroyCallback) {
+ mDestroyCallback(mPluginInstanceOwner);
+ }
+ }
+
+ /**
+ * This can only be called on the main thread. It may add a reference
+ * to the surface (which will eventually be released on the main thread).
+ * The surface must not be modified after this call!!!
+ */
+ virtual void SetData(const Data& aData);
+
+ /**
+ * Temporary hacks to force plugin drawing during an empty transaction.
+ * This should not be used for anything else, and will be removed
+ * when async plugin rendering is complete.
+ */
+ typedef void (*UpdateSurfaceCallback)(ImageContainer* aContainer, void* aInstanceOwner);
+ virtual void SetUpdateCallback(UpdateSurfaceCallback aCallback, void* aInstanceOwner)
+ {
+ mUpdateCallback = aCallback;
+ mPluginInstanceOwner = aInstanceOwner;
+ }
+
+ typedef void (*DestroyCallback)(void* aInstanceOwner);
+ virtual void SetDestroyCallback(DestroyCallback aCallback)
+ {
+ mDestroyCallback = aCallback;
+ }
+
+ virtual gfxIntSize GetSize()
+ {
+ return mSize;
+ }
+
+ MacIOSurface* GetIOSurface()
+ {
+ return mIOSurface;
+ }
+
+ void Update(ImageContainer* aContainer);
+
+ virtual already_AddRefed<gfxASurface> GetAsSurface();
+
+private:
+ gfxIntSize mSize;
+ RefPtr<MacIOSurface> mIOSurface;
+ void* mPluginInstanceOwner;
+ UpdateSurfaceCallback mUpdateCallback;
+ DestroyCallback mDestroyCallback;
+};
+#endif
+
+class RemoteBitmapImage : public Image {
+public:
+ RemoteBitmapImage() : Image(NULL, REMOTE_IMAGE_BITMAP) {}
+
+ already_AddRefed<gfxASurface> GetAsSurface();
+
+ gfxIntSize GetSize() { return mSize; }
+
+ unsigned char *mData;
+ int mStride;
+ gfxIntSize mSize;
+ RemoteImageData::Format mFormat;
+};
+
+
+} //namespace
+} //namespace
+
+#endif
\ No newline at end of file
--- a/gfx/layers/ImageLayers.cpp
+++ b/gfx/layers/ImageLayers.cpp
@@ -1,548 +1,44 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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 "mozilla/ipc/Shmem.h"
-#include "mozilla/ipc/CrossProcessMutex.h"
#include "ImageLayers.h"
-#include "SharedTextureImage.h"
-#include "gfxImageSurface.h"
-#include "gfxSharedImageSurface.h"
-#include "yuv_convert.h"
-#include "gfxUtils.h"
-#include "mozilla/layers/ImageBridgeChild.h"
-#include "mozilla/layers/ImageContainerChild.h"
-#include "GonkIOSurfaceImage.h"
-
-#ifdef XP_MACOSX
-#include "mozilla/gfx/QuartzSupport.h"
-#endif
-
-#ifdef XP_WIN
-#include "gfxD2DSurface.h"
-#include "gfxWindowsPlatform.h"
-#include <d3d10_1.h>
-
-#include "d3d10/ImageLayerD3D10.h"
-#endif
-
-using namespace mozilla::ipc;
-using mozilla::gfx::DataSourceSurface;
-using mozilla::gfx::SourceSurface;
+#include "ImageContainer.h"
namespace mozilla {
namespace layers {
-already_AddRefed<Image>
-ImageFactory::CreateImage(const Image::Format *aFormats,
- PRUint32 aNumFormats,
- const gfxIntSize &,
- BufferRecycleBin *aRecycleBin)
-{
- if (!aNumFormats) {
- return nullptr;
- }
- nsRefPtr<Image> img;
- if (FormatInList(aFormats, aNumFormats, Image::PLANAR_YCBCR)) {
- img = new PlanarYCbCrImage(aRecycleBin);
- } else if (FormatInList(aFormats, aNumFormats, Image::CAIRO_SURFACE)) {
- img = new CairoImage();
- } else if (FormatInList(aFormats, aNumFormats, Image::SHARED_TEXTURE)) {
- img = new SharedTextureImage();
-#ifdef XP_MACOSX
- } else if (FormatInList(aFormats, aNumFormats, Image::MAC_IO_SURFACE)) {
- img = new MacIOSurfaceImage();
-#endif
-#ifdef MOZ_WIDGET_GONK
- } else if (FormatInList(aFormats, aNumFormats, Image::GONK_IO_SURFACE)) {
- img = new GonkIOSurfaceImage();
-#endif
- }
- return img.forget();
-}
-
-BufferRecycleBin::BufferRecycleBin()
- : mLock("mozilla.layers.BufferRecycleBin.mLock")
-{
-}
-
-void
-BufferRecycleBin::RecycleBuffer(PRUint8* aBuffer, PRUint32 aSize)
-{
- MutexAutoLock lock(mLock);
-
- if (!mRecycledBuffers.IsEmpty() && aSize != mRecycledBufferSize) {
- mRecycledBuffers.Clear();
- }
- mRecycledBufferSize = aSize;
- mRecycledBuffers.AppendElement(aBuffer);
-}
-
-PRUint8*
-BufferRecycleBin::GetBuffer(PRUint32 aSize)
-{
- MutexAutoLock lock(mLock);
-
- if (mRecycledBuffers.IsEmpty() || mRecycledBufferSize != aSize)
- return new PRUint8[aSize];
-
- PRUint32 last = mRecycledBuffers.Length() - 1;
- PRUint8* result = mRecycledBuffers[last].forget();
- mRecycledBuffers.RemoveElementAt(last);
- return result;
-}
-
-ImageContainer::ImageContainer(int flag)
-: mReentrantMonitor("ImageContainer.mReentrantMonitor"),
- mPaintCount(0),
- mPreviousImagePainted(false),
- mImageFactory(new ImageFactory()),
- mRecycleBin(new BufferRecycleBin()),
- mRemoteData(nullptr),
- mRemoteDataMutex(nullptr),
- mCompositionNotifySink(nullptr),
- mImageContainerChild(nullptr)
-{
- if (flag == ENABLE_ASYNC && ImageBridgeChild::IsCreated()) {
- mImageContainerChild =
- ImageBridgeChild::GetSingleton()->CreateImageContainerChild();
- }
-}
-
-ImageContainer::~ImageContainer()
-{
- if (mImageContainerChild) {
- mImageContainerChild->DispatchStop();
- }
-}
-
-already_AddRefed<Image>
-ImageContainer::CreateImage(const Image::Format *aFormats,
- PRUint32 aNumFormats)
-{
- ReentrantMonitorAutoEnter mon(mReentrantMonitor);
- return mImageFactory->CreateImage(aFormats, aNumFormats, mScaleHint, mRecycleBin);
-}
-
-void
-ImageContainer::SetCurrentImageInternal(Image *aImage)
-{
- ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-
- if (mRemoteData) {
- NS_ASSERTION(mRemoteDataMutex, "Should have remote data mutex when having remote data!");
- mRemoteDataMutex->Lock();
- // This is important since it ensures we won't change the active image
- // when we currently have a locked image that depends on mRemoteData.
- }
-
- mActiveImage = aImage;
- CurrentImageChanged();
-
- if (mRemoteData) {
- mRemoteDataMutex->Unlock();
- }
-}
-
-void
-ImageContainer::SetCurrentImage(Image *aImage)
-{
- ReentrantMonitorAutoEnter mon(mReentrantMonitor);
+ImageLayer::ImageLayer(LayerManager* aManager, void* aImplData)
+: Layer(aManager, aImplData), mFilter(gfxPattern::FILTER_GOOD)
+, mScaleMode(SCALE_NONE), mForceSingleTile(false)
+{}
- if (mImageContainerChild) {
- if (aImage) {
- mImageContainerChild->SendImageAsync(this, aImage);
- } else {
- mImageContainerChild->DispatchSetIdle();
- }
- }
-
- SetCurrentImageInternal(aImage);
-}
-
-void
-ImageContainer::SetCurrentImageInTransaction(Image *aImage)
-{
- NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
- NS_ASSERTION(!mImageContainerChild, "Should use async image transfer with ImageBridge.");
-
- SetCurrentImageInternal(aImage);
-}
-
-bool ImageContainer::IsAsync() const {
- return mImageContainerChild != nullptr;
-}
-
-PRUint64 ImageContainer::GetAsyncContainerID() const
-{
- NS_ASSERTION(IsAsync(),"Shared image ID is only relevant to async ImageContainers");
- if (IsAsync()) {
- return mImageContainerChild->GetID();
- } else {
- return 0; // zero is always an invalid SharedImageID
- }
-}
-
-bool
-ImageContainer::HasCurrentImage()
-{
- ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-
- if (mRemoteData) {
- CrossProcessMutexAutoLock autoLock(*mRemoteDataMutex);
-
- EnsureActiveImage();
-
- return !!mActiveImage.get();
- }
-
- return !!mActiveImage.get();
-}
-
-already_AddRefed<Image>
-ImageContainer::LockCurrentImage()
-{
- ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-
- if (mRemoteData) {
- NS_ASSERTION(mRemoteDataMutex, "Should have remote data mutex when having remote data!");
- mRemoteDataMutex->Lock();
- }
+ImageLayer::~ImageLayer()
+{}
- EnsureActiveImage();
-
- nsRefPtr<Image> retval = mActiveImage;
- return retval.forget();
-}
-
-already_AddRefed<gfxASurface>
-ImageContainer::LockCurrentAsSurface(gfxIntSize *aSize, Image** aCurrentImage)
+void ImageLayer::SetContainer(ImageContainer* aContainer)
{
- ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-
- if (mRemoteData) {
- NS_ASSERTION(mRemoteDataMutex, "Should have remote data mutex when having remote data!");
- mRemoteDataMutex->Lock();
-
- EnsureActiveImage();
-
- if (aCurrentImage) {
- NS_IF_ADDREF(mActiveImage);
- *aCurrentImage = mActiveImage.get();
- }
-
- if (!mActiveImage) {
- return nullptr;
- }
-
- if (mActiveImage->GetFormat() == Image::REMOTE_IMAGE_BITMAP) {
- nsRefPtr<gfxImageSurface> newSurf =
- new gfxImageSurface(mRemoteData->mBitmap.mData, mRemoteData->mSize, mRemoteData->mBitmap.mStride,
- mRemoteData->mFormat == RemoteImageData::BGRX32 ?
- gfxASurface::ImageFormatARGB32 :
- gfxASurface::ImageFormatRGB24);
-
- *aSize = newSurf->GetSize();
-
- return newSurf.forget();
- }
-
- *aSize = mActiveImage->GetSize();
- return mActiveImage->GetAsSurface();
- }
-
- if (aCurrentImage) {
- NS_IF_ADDREF(mActiveImage);
- *aCurrentImage = mActiveImage.get();
- }
-
- if (!mActiveImage) {
- return nullptr;
- }
-
- *aSize = mActiveImage->GetSize();
- return mActiveImage->GetAsSurface();
-}
-
-void
-ImageContainer::UnlockCurrentImage()
-{
- if (mRemoteData) {
- NS_ASSERTION(mRemoteDataMutex, "Should have remote data mutex when having remote data!");
- mRemoteDataMutex->Unlock();
- }
+ mContainer = aContainer;
}
-already_AddRefed<gfxASurface>
-ImageContainer::GetCurrentAsSurface(gfxIntSize *aSize)
-{
- ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-
- if (mRemoteData) {
- CrossProcessMutexAutoLock autoLock(*mRemoteDataMutex);
- EnsureActiveImage();
-
- if (!mActiveImage)
- return nullptr;
- *aSize = mRemoteData->mSize;
- } else {
- if (!mActiveImage)
- return nullptr;
- *aSize = mActiveImage->GetSize();
- }
- return mActiveImage->GetAsSurface();
-}
-
-gfxIntSize
-ImageContainer::GetCurrentSize()
-{
- ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-
- if (mRemoteData) {
- CrossProcessMutexAutoLock autoLock(*mRemoteDataMutex);
-
- // We don't need to ensure we have an active image here, as we need to
- // be in the mutex anyway, and this is easiest to return from there.
- return mRemoteData->mSize;
- }
-
- if (!mActiveImage) {
- return gfxIntSize(0,0);
- }
-
- return mActiveImage->GetSize();
-}
-
-void
-ImageContainer::SetRemoteImageData(RemoteImageData *aData, CrossProcessMutex *aMutex)
-{
- ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-
- NS_ASSERTION(!mActiveImage || !aData, "No active image expected when SetRemoteImageData is called with non-NULL aData.");
- NS_ASSERTION(!mRemoteData || !aData, "No remote data expected when SetRemoteImageData is called with non-NULL aData.");
-
- mRemoteData = aData;
-
- if (aData) {
- memset(aData, 0, sizeof(RemoteImageData));
- } else {
- mActiveImage = nullptr;
- }
-
- mRemoteDataMutex = aMutex;
-}
-
-void
-ImageContainer::EnsureActiveImage()
-{
- if (mRemoteData) {
- if (mRemoteData->mWasUpdated) {
- mActiveImage = nullptr;
- }
-
- if (mRemoteData->mType == RemoteImageData::RAW_BITMAP &&
- mRemoteData->mBitmap.mData && !mActiveImage) {
- nsRefPtr<RemoteBitmapImage> newImg = new RemoteBitmapImage();
-
- newImg->mFormat = mRemoteData->mFormat;
- newImg->mData = mRemoteData->mBitmap.mData;
- newImg->mSize = mRemoteData->mSize;
- newImg->mStride = mRemoteData->mBitmap.mStride;
- mRemoteData->mWasUpdated = false;
-
- mActiveImage = newImg;
- }
-#ifdef XP_WIN
- else if (mRemoteData->mType == RemoteImageData::DXGI_TEXTURE_HANDLE &&
- mRemoteData->mTextureHandle && !mActiveImage) {
- nsRefPtr<RemoteDXGITextureImage> newImg = new RemoteDXGITextureImage();
- newImg->mSize = mRemoteData->mSize;
- newImg->mHandle = mRemoteData->mTextureHandle;
- newImg->mFormat = mRemoteData->mFormat;
- mRemoteData->mWasUpdated = false;
-
- mActiveImage = newImg;
- }
-#endif
- }
-}
-
-PlanarYCbCrImage::PlanarYCbCrImage(BufferRecycleBin *aRecycleBin)
- : Image(nullptr, PLANAR_YCBCR)
- , mBufferSize(0)
- , mRecycleBin(aRecycleBin)
-{
-}
-
-PlanarYCbCrImage::~PlanarYCbCrImage()
-{
- if (mBuffer) {
- mRecycleBin->RecycleBuffer(mBuffer.forget(), mBufferSize);
- }
-}
-
-PRUint8*
-PlanarYCbCrImage::AllocateBuffer(PRUint32 aSize)
-{
- return mRecycleBin->GetBuffer(aSize);
-}
-
-static void
-CopyPlane(PRUint8 *aDst, PRUint8 *aSrc,
- const gfxIntSize &aSize, PRInt32 aStride,
- PRInt32 aOffset, PRInt32 aSkip)
+void ImageLayer::ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
{
- if (!aOffset && !aSkip) {
- // Fast path: planar input.
- memcpy(aDst, aSrc, aSize.height * aStride);
- } else {
- PRInt32 height = aSize.height;
- PRInt32 width = aSize.width;
- for (int y = 0; y < height; ++y) {
- PRUint8 *src = aSrc + aOffset;
- PRUint8 *dst = aDst;
- if (!aSkip) {
- // Fast path: offset only, no per-pixel skip.
- memcpy(dst, src, width);
- } else {
- // Slow path
- for (int x = 0; x < width; ++x) {
- *dst++ = *src++;
- src += aSkip;
- }
- }
- aSrc += aStride;
- aDst += aStride;
- }
- }
-}
-
-void
-PlanarYCbCrImage::CopyData(const Data& aData,
- PRInt32 aYOffset, PRInt32 aYSkip,
- PRInt32 aCbOffset, PRInt32 aCbSkip,
- PRInt32 aCrOffset, PRInt32 aCrSkip)
-{
- mData = aData;
-
- // update buffer size
- mBufferSize = mData.mCbCrStride * mData.mCbCrSize.height * 2 +
- mData.mYStride * mData.mYSize.height;
-
- // get new buffer
- mBuffer = AllocateBuffer(mBufferSize);
- if (!mBuffer)
- return;
-
- mData.mYChannel = mBuffer;
- mData.mCbChannel = mData.mYChannel + mData.mYStride * mData.mYSize.height;
- mData.mCrChannel = mData.mCbChannel + mData.mCbCrStride * mData.mCbCrSize.height;
-
- CopyPlane(mData.mYChannel, aData.mYChannel,
- mData.mYSize, mData.mYStride,
- aYOffset, aYSkip);
- CopyPlane(mData.mCbChannel, aData.mCbChannel,
- mData.mCbCrSize, mData.mCbCrStride,
- aCbOffset, aCbSkip);
- CopyPlane(mData.mCrChannel, aData.mCrChannel,
- mData.mCbCrSize, mData.mCbCrStride,
- aCrOffset, aCrSkip);
-
- mSize = aData.mPicSize;
-}
-
-void
-PlanarYCbCrImage::SetData(const Data &aData)
-{
- CopyData(aData);
-}
-
-already_AddRefed<gfxASurface>
-PlanarYCbCrImage::GetAsSurface()
-{
- if (mSurface) {
- nsRefPtr<gfxASurface> result = mSurface.get();
- return result.forget();
+ // Snap image edges to pixel boundaries
+ gfxRect snap(0, 0, 0, 0);
+ if (mContainer) {
+ gfxIntSize size = mContainer->GetCurrentSize();
+ snap.SizeTo(gfxSize(size.width, size.height));
}
-
- gfxASurface::gfxImageFormat format = GetOffscreenFormat();
-
- gfxIntSize size(mSize);
- gfxUtils::GetYCbCrToRGBDestFormatAndSize(mData, format, size);
- if (size.width > PlanarYCbCrImage::MAX_DIMENSION ||
- size.height > PlanarYCbCrImage::MAX_DIMENSION) {
- NS_ERROR("Illegal image dest width or height");
- return nullptr;
- }
-
- nsRefPtr<gfxImageSurface> imageSurface =
- new gfxImageSurface(mSize, format);
-
- gfxUtils::ConvertYCbCrToRGB(mData, format, mSize,
- imageSurface->Data(),
- imageSurface->Stride());
-
- mSurface = imageSurface;
-
- return imageSurface.forget().get();
-}
-
-#ifdef XP_MACOSX
-void
-MacIOSurfaceImage::SetData(const Data& aData)
-{
- mIOSurface = MacIOSurface::LookupSurface(aData.mIOSurface->GetIOSurfaceID());
- mSize = gfxIntSize(mIOSurface->GetWidth(), mIOSurface->GetHeight());
-}
-
-already_AddRefed<gfxASurface>
-MacIOSurfaceImage::GetAsSurface()
-{
- mIOSurface->Lock();
- size_t bytesPerRow = mIOSurface->GetBytesPerRow();
- size_t ioWidth = mIOSurface->GetWidth();
- size_t ioHeight = mIOSurface->GetHeight();
-
- unsigned char* ioData = (unsigned char*)mIOSurface->GetBaseAddress();
-
- nsRefPtr<gfxImageSurface> imgSurface =
- new gfxImageSurface(gfxIntSize(ioWidth, ioHeight), gfxASurface::ImageFormatARGB32);
-
- for (int i = 0; i < ioHeight; i++) {
- memcpy(imgSurface->Data() + i * imgSurface->Stride(),
- ioData + i * bytesPerRow, ioWidth * 4);
- }
-
- mIOSurface->Unlock();
-
- return imgSurface.forget();
-}
-
-void
-MacIOSurfaceImage::Update(ImageContainer* aContainer)
-{
- if (mUpdateCallback) {
- mUpdateCallback(aContainer, mPluginInstanceOwner);
- }
-}
-#endif
-
-already_AddRefed<gfxASurface>
-RemoteBitmapImage::GetAsSurface()
-{
- nsRefPtr<gfxImageSurface> newSurf =
- new gfxImageSurface(mSize,
- mFormat == RemoteImageData::BGRX32 ? gfxASurface::ImageFormatRGB24 : gfxASurface::ImageFormatARGB32);
-
- for (int y = 0; y < mSize.height; y++) {
- memcpy(newSurf->Data() + newSurf->Stride() * y,
- mData + mStride * y,
- mSize.width * 4);
- }
-
- return newSurf.forget();
+ // Snap our local transform first, and snap the inherited transform as well.
+ // This makes our snapping equivalent to what would happen if our content
+ // was drawn into a ThebesLayer (gfxContext would snap using the local
+ // transform, then we'd snap again when compositing the ThebesLayer).
+ mEffectiveTransform =
+ SnapTransform(GetLocalTransform(), snap, nullptr)*
+ SnapTransform(aTransformToSurface, gfxRect(0, 0, 0, 0), nullptr);
+ ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
}
}
}
--- a/gfx/layers/ImageLayers.h
+++ b/gfx/layers/ImageLayers.h
@@ -3,652 +3,24 @@
* 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 GFX_IMAGELAYER_H
#define GFX_IMAGELAYER_H
#include "Layers.h"
+#include "ImageTypes.h"
#include "nsISupportsImpl.h"
#include "gfxPattern.h"
-#include "nsThreadUtils.h"
-#include "mozilla/ReentrantMonitor.h"
-#include "mozilla/TimeStamp.h"
-#include "mozilla/mozalloc.h"
-#include "mozilla/Mutex.h"
-#include "gfxPlatform.h"
-
-#ifdef XP_MACOSX
-#include "mozilla/gfx/MacIOSurface.h"
-#endif
-#ifdef XP_WIN
-struct ID3D10Texture2D;
-struct ID3D10Device;
-struct ID3D10ShaderResourceView;
-
-typedef void* HANDLE;
-#endif
namespace mozilla {
-
-class CrossProcessMutex;
-namespace ipc {
-class Shmem;
-}
-
namespace layers {
-class ImageContainerChild;
-class ImageBridgeChild;
-
-enum StereoMode {
- STEREO_MODE_MONO,
- STEREO_MODE_LEFT_RIGHT,
- STEREO_MODE_RIGHT_LEFT,
- STEREO_MODE_BOTTOM_TOP,
- STEREO_MODE_TOP_BOTTOM
-};
-
-struct ImageBackendData
-{
- virtual ~ImageBackendData() {}
-
-protected:
- ImageBackendData() {}
-};
-
-/**
- * A class representing a buffer of pixel data. The data can be in one
- * of various formats including YCbCr.
- *
- * Create an image using an ImageContainer. Fill the image with data, and
- * then call ImageContainer::SetImage to display it. An image must not be
- * modified after calling SetImage. Image implementations do not need to
- * perform locking; when filling an Image, the Image client is responsible
- * for ensuring only one thread accesses the Image at a time, and after
- * SetImage the image is immutable.
- *
- * When resampling an Image, only pixels within the buffer should be
- * sampled. For example, cairo images should be sampled in EXTEND_PAD mode.
- */
-class THEBES_API Image {
- NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Image)
-
-public:
- virtual ~Image() {}
-
- enum Format {
- /**
- * The PLANAR_YCBCR format creates a PlanarYCbCrImage. All backends should
- * support this format, because the Ogg video decoder depends on it.
- * The maximum image width and height is 16384.
- */
- PLANAR_YCBCR,
-
- /**
- * The CAIRO_SURFACE format creates a CairoImage. All backends should
- * support this format, because video rendering sometimes requires it.
- *
- * This format is useful even though a ThebesLayer could be used.
- * It makes it easy to render a cairo surface when another Image format
- * could be used. It can also avoid copying the surface data in some
- * cases.
- *
- * Images in CAIRO_SURFACE format should only be created and
- * manipulated on the main thread, since the underlying cairo surface
- * is main-thread-only.
- */
- CAIRO_SURFACE,
-
- /**
- * The MAC_IO_SURFACE format creates a MacIOSurfaceImage.
- *
- * It wraps an IOSurface object and binds it directly to a GL texture.
- */
- MAC_IO_SURFACE,
-
- /**
- * The GONK_IO_SURFACE format creates a GonkIOSurfaceImage.
- *
- * It wraps an GraphicBuffer object and binds it directly to a GL texture.
- */
- GONK_IO_SURFACE,
-
- /**
- * An bitmap image that can be shared with a remote process.
- */
- REMOTE_IMAGE_BITMAP,
-
- /**
- * A OpenGL texture that can be shared across threads or processes
- */
- SHARED_TEXTURE,
-
- /**
- * An DXGI shared surface handle that can be shared with a remote process.
- */
- REMOTE_IMAGE_DXGI_TEXTURE
- };
-
- Format GetFormat() { return mFormat; }
- void* GetImplData() { return mImplData; }
-
- virtual already_AddRefed<gfxASurface> GetAsSurface() = 0;
- virtual gfxIntSize GetSize() = 0;
-
- ImageBackendData* GetBackendData(LayersBackend aBackend)
- { return mBackendData[aBackend]; }
- void SetBackendData(LayersBackend aBackend, ImageBackendData* aData)
- { mBackendData[aBackend] = aData; }
-
-protected:
- Image(void* aImplData, Format aFormat) :
- mImplData(aImplData),
- mFormat(aFormat)
- {}
-
- nsAutoPtr<ImageBackendData> mBackendData[mozilla::layers::LAYERS_LAST];
-
- void* mImplData;
- Format mFormat;
-};
-
-/**
- * A RecycleBin is owned by an ImageContainer. We store buffers in it that we
- * want to recycle from one image to the next.It's a separate object from
- * ImageContainer because images need to store a strong ref to their RecycleBin
- * and we must avoid creating a reference loop between an ImageContainer and
- * its active image.
- */
-class BufferRecycleBin {
- NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RecycleBin)
-
- typedef mozilla::gl::GLContext GLContext;
-
-public:
- BufferRecycleBin();
-
- void RecycleBuffer(PRUint8* aBuffer, PRUint32 aSize);
- // Returns a recycled buffer of the right size, or allocates a new buffer.
- PRUint8* GetBuffer(PRUint32 aSize);
-
-private:
- typedef mozilla::Mutex Mutex;
-
- // This protects mRecycledBuffers, mRecycledBufferSize, mRecycledTextures
- // and mRecycledTextureSizes
- Mutex mLock;
-
- // We should probably do something to prune this list on a timer so we don't
- // eat excess memory while video is paused...
- nsTArray<nsAutoArrayPtr<PRUint8> > mRecycledBuffers;
- // This is only valid if mRecycledBuffers is non-empty
- PRUint32 mRecycledBufferSize;
-};
-
-/**
- * Returns true if aFormat is in the given format array.
- */
-static inline bool
-FormatInList(const Image::Format* aFormats, PRUint32 aNumFormats,
- Image::Format aFormat)
-{
- for (PRUint32 i = 0; i < aNumFormats; ++i) {
- if (aFormats[i] == aFormat) {
- return true;
- }
- }
- return false;
-}
-
-class CompositionNotifySink
-{
-public:
- virtual void DidComposite() = 0;
- virtual ~CompositionNotifySink() {}
-};
-
-/**
- * A class that manages Image creation for a LayerManager. The only reason
- * we need a separate class here is that LayerMananers aren't threadsafe
- * (because layers can only be used on the main thread) and we want to
- * be able to create images from any thread, to facilitate video playback
- * without involving the main thread, for example.
- * Different layer managers can implement child classes of this making it
- * possible to create layer manager specific images.
- * This class is not meant to be used directly but rather can be set on an
- * image container. This is usually done by the layer system internally and
- * not explicitly by users. For PlanarYCbCr or Cairo images the default
- * implementation will creates images whose data lives in system memory, for
- * MacIOSurfaces the default implementation will be a simple MacIOSurface
- * wrapper.
- */
-
-class THEBES_API ImageFactory
-{
- NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ImageFactory)
-protected:
- friend class ImageContainer;
-
- ImageFactory() {}
- virtual ~ImageFactory() {}
-
- virtual already_AddRefed<Image> CreateImage(const Image::Format* aFormats,
- PRUint32 aNumFormats,
- const gfxIntSize &aScaleHint,
- BufferRecycleBin *aRecycleBin);
-
-};
-
-/**
- * This struct is used to store RemoteImages, it is meant to be able to live in
- * shared memory. Therefor it should not contain a vtable pointer. Remote
- * users can manipulate the data in this structure to specify what image is to
- * be drawn by the container. When accessing this data users should make sure
- * the mutex synchronizing access to the structure is held!
- */
-struct RemoteImageData {
- enum Type {
- /**
- * This is a format that uses raw bitmap data.
- */
- RAW_BITMAP,
-
- /**
- * This is a format that uses a pointer to a texture do draw directly
- * from a shared texture. Any process may have created this texture handle,
- * the process creating the texture handle is responsible for managing it's
- * lifetime by managing the lifetime of the first D3D texture object this
- * handle was created for. It must also ensure the handle is not set
- * current anywhere when the last reference to this object is released.
- */
- DXGI_TEXTURE_HANDLE
- };
- /* These formats describe the format in the memory byte-order */
- enum Format {
- /* 8 bits per channel */
- BGRA32,
- /* 8 bits per channel, alpha channel is ignored */
- BGRX32
- };
-
- // This should be set to true if a change was made so that the ImageContainer
- // knows to throw out any cached RemoteImage objects.
- bool mWasUpdated;
- Type mType;
- Format mFormat;
- gfxIntSize mSize;
- union {
- struct {
- /* This pointer is set by a remote process, however it will be set to
- * the container process' address the memory of the raw bitmap resides
- * at.
- */
- unsigned char *mData;
- int mStride;
- } mBitmap;
-#ifdef XP_WIN
- HANDLE mTextureHandle;
-#endif
- };
-};
-
-/**
- * A class that manages Images for an ImageLayer. The only reason
- * we need a separate class here is that ImageLayers aren't threadsafe
- * (because layers can only be used on the main thread) and we want to
- * be able to set the current Image from any thread, to facilitate
- * video playback without involving the main thread, for example.
- *
- * An ImageContainer can operate in one of three modes:
- * 1) Normal. Triggered by constructing the ImageContainer with
- * DISABLE_ASYNC or when compositing is happening on the main thread.
- * SetCurrentImage changes ImageContainer state but nothing is sent to the
- * compositor until the next layer transaction.
- * 2) Asynchronous. Initiated by constructing the ImageContainer with
- * ENABLE_ASYNC when compositing is happening on the main thread.
- * SetCurrentImage sends a message through the ImageBridge to the compositor
- * thread to update the image, without going through the main thread or
- * a layer transaction.
- * 3) Remote. Initiated by calling SetRemoteImageData on the ImageContainer
- * before any other activity.
- * The ImageContainer uses a shared memory block containing a cross-process mutex
- * to communicate with the compositor thread. SetCurrentImage synchronously
- * updates the shared state to point to the new image and the old image
- * is immediately released (not true in Normal or Asynchronous modes).
- */
-class THEBES_API ImageContainer {
- NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ImageContainer)
-public:
-
- enum { DISABLE_ASYNC = 0x0, ENABLE_ASYNC = 0x01 };
-
- ImageContainer(int flag = 0);
-
- ~ImageContainer();
-
- /**
- * Create an Image in one of the given formats.
- * Picks the "best" format from the list and creates an Image of that
- * format.
- * Returns null if this backend does not support any of the formats.
- * Can be called on any thread. This method takes mReentrantMonitor
- * when accessing thread-shared state.
- */
- already_AddRefed<Image> CreateImage(const Image::Format* aFormats,
- PRUint32 aNumFormats);
-
- /**
- * Set an Image as the current image to display. The Image must have
- * been created by this ImageContainer.
- * Can be called on any thread. This method takes mReentrantMonitor
- * when accessing thread-shared state.
- * aImage can be null. While it's null, nothing will be painted.
- *
- * The Image data must not be modified after this method is called!
- * Note that this must not be called if ENABLE_ASYNC has not been set.
- *
- * Implementations must call CurrentImageChanged() while holding
- * mReentrantMonitor.
- *
- * If this ImageContainer has an ImageContainerChild for async video:
- * Schelude a task to send the image to the compositor using the
- * PImageBridge protcol without using the main thread.
- */
- void SetCurrentImage(Image* aImage);
-
- /**
- * Set an Image as the current image to display. The Image must have
- * been created by this ImageContainer.
- * Must be called on the main thread, within a layers transaction.
- *
- * This method takes mReentrantMonitor
- * when accessing thread-shared state.
- * aImage can be null. While it's null, nothing will be painted.
- *
- * The Image data must not be modified after this method is called!
- * Note that this must not be called if ENABLE_ASYNC been set.
- *
- * Implementations must call CurrentImageChanged() while holding
- * mReentrantMonitor.
- */
- void SetCurrentImageInTransaction(Image* aImage);
-
- /**
- * Returns true if this ImageContainer uses the ImageBridge IPDL protocol.
- *
- * Can be called from any thread.
- */
- bool IsAsync() const;
-
- /**
- * If this ImageContainer uses ImageBridge, returns the ID associated to
- * this container, for use in the ImageBridge protocol.
- * Returns 0 if this ImageContainer does not use ImageBridge. Note that
- * 0 is always an invalid ID for asynchronous image containers.
- *
- * Can be called from ay thread.
- */
- PRUint64 GetAsyncContainerID() const;
-
- /**
- * Returns if the container currently has an image.
- * Can be called on any thread. This method takes mReentrantMonitor
- * when accessing thread-shared state.
- */
- bool HasCurrentImage();
-
- /**
- * Lock the current Image.
- * This has to add a reference since otherwise there are race conditions
- * where the current image is destroyed before the caller can add
- * a reference. This lock strictly guarantees the underlying image remains
- * valid, it does not mean the current image cannot change.
- * Can be called on any thread. This method will lock the cross-process
- * mutex to ensure remote processes cannot alter underlying data. This call
- * -must- be balanced by a call to UnlockCurrentImage and users should avoid
- * holding the image locked for a long time.
- */
- already_AddRefed<Image> LockCurrentImage();
-
- /**
- * This call unlocks the image. For remote images releasing the cross-process
- * mutex.
- */
- void UnlockCurrentImage();
-
- /**
- * Get the current image as a gfxASurface. This is useful for fallback
- * rendering.
- * This can only be called from the main thread, since cairo objects
- * can only be used from the main thread.
- * This is defined here and not on Image because it's possible (likely)
- * that some backends will make an Image "ready to draw" only when it
- * becomes the current image for an image container.
- * Returns null if there is no current image.
- * Returns the size in aSize.
- * The returned surface will never be modified. The caller must not
- * modify it.
- * Can be called on any thread. This method takes mReentrantMonitor
- * when accessing thread-shared state.
- * If the current image is a remote image, that is, if it is an image that
- * may be shared accross processes, calling this function will make
- * a copy of the image data while holding the mRemoteDataMutex. If possible,
- * the lock methods should be used to avoid the copy, however this should be
- * avoided if the surface is required for a long period of time.
- */
- already_AddRefed<gfxASurface> GetCurrentAsSurface(gfxIntSize* aSizeResult);
-
- /**
- * This is similar to GetCurrentAsSurface, however this does not make a copy
- * of the image data and requires the user to call UnlockCurrentImage when
- * done with the image data. Once UnlockCurrentImage has been called the
- * surface returned by this function is no longer valid! This works for any
- * type of image. Optionally a pointer can be passed to receive the current
- * image.
- */
- already_AddRefed<gfxASurface> LockCurrentAsSurface(gfxIntSize* aSizeResult,
- Image** aCurrentImage = nullptr);
-
- /**
- * Returns the size of the image in pixels.
- * Can be called on any thread. This method takes mReentrantMonitor when accessing
- * thread-shared state.
- */
- gfxIntSize GetCurrentSize();
-
- /**
- * Sets a size that the image is expected to be rendered at.
- * This is a hint for image backends to optimize scaling.
- * Default implementation in this class is to ignore the hint.
- * Can be called on any thread. This method takes mReentrantMonitor
- * when accessing thread-shared state.
- */
- void SetScaleHint(const gfxIntSize& aScaleHint)
- { mScaleHint = aScaleHint; }
-
- void SetImageFactory(ImageFactory *aFactory)
- {
- ReentrantMonitorAutoEnter mon(mReentrantMonitor);
- mImageFactory = aFactory ? aFactory : new ImageFactory();
- }
-
- /**
- * Returns the time at which the currently contained image was first
- * painted. This is reset every time a new image is set as the current
- * image. Note this may return a null timestamp if the current image
- * has not yet been painted. Can be called from any thread.
- */
- TimeStamp GetPaintTime() {
- ReentrantMonitorAutoEnter mon(mReentrantMonitor);
- return mPaintTime;
- }
-
- /**
- * Returns the number of images which have been contained in this container
- * and painted at least once. Can be called from any thread.
- */
- PRUint32 GetPaintCount() {
- ReentrantMonitorAutoEnter mon(mReentrantMonitor);
- return mPaintCount;
- }
-
- /**
- * Increments mPaintCount if this is the first time aPainted has been
- * painted, and sets mPaintTime if the painted image is the current image.
- * current image. Can be called from any thread.
- */
- void NotifyPaintedImage(Image* aPainted) {
- ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-
- nsRefPtr<Image> current = mActiveImage;
- if (aPainted == current) {
- if (mPaintTime.IsNull()) {
- mPaintTime = TimeStamp::Now();
- mPaintCount++;
- }
- } else if (!mPreviousImagePainted) {
- // While we were painting this image, the current image changed. We
- // still must count it as painted, but can't set mPaintTime, since we're
- // no longer the current image.
- mPaintCount++;
- mPreviousImagePainted = true;
- }
-
- if (mCompositionNotifySink) {
- mCompositionNotifySink->DidComposite();
- }
- }
-
- void SetCompositionNotifySink(CompositionNotifySink *aSink) {
- mCompositionNotifySink = aSink;
- }
-
- /**
- * This function is called to tell the ImageContainer where the
- * (cross-process) segment lives where the shared data about possible
- * remote images are stored. In addition to this a CrossProcessMutex object
- * is passed telling the container how to synchronize access to this data.
- * NOTE: This should be called during setup of the container and not after
- * usage has started.
- */
- void SetRemoteImageData(RemoteImageData *aRemoteData,
- CrossProcessMutex *aRemoteDataMutex);
- /**
- * This can be used to check if the container has RemoteData set.
- */
- RemoteImageData *GetRemoteImageData() { return mRemoteData; }
-
-protected:
- typedef mozilla::ReentrantMonitor ReentrantMonitor;
-
- void SetCurrentImageInternal(Image* aImage);
-
- // This is called to ensure we have an active image, this may not be true
- // when we're storing image information in a RemoteImageData structure.
- // NOTE: If we have remote data mRemoteDataMutex should be locked when
- // calling this function!
- void EnsureActiveImage();
-
- // ReentrantMonitor to protect thread safe access to the "current
- // image", and any other state which is shared between threads.
- ReentrantMonitor mReentrantMonitor;
-
- // Performs necessary housekeeping to ensure the painted frame statistics
- // are accurate. Must be called by SetCurrentImage() implementations with
- // mReentrantMonitor held.
- void CurrentImageChanged() {
- mReentrantMonitor.AssertCurrentThreadIn();
- mPreviousImagePainted = !mPaintTime.IsNull();
- mPaintTime = TimeStamp();
- }
-
- nsRefPtr<Image> mActiveImage;
-
- // Number of contained images that have been painted at least once. It's up
- // to the ImageContainer implementation to ensure accesses to this are
- // threadsafe.
- PRUint32 mPaintCount;
-
- // Time stamp at which the current image was first painted. It's up to the
- // ImageContainer implementation to ensure accesses to this are threadsafe.
- TimeStamp mPaintTime;
-
- // Denotes whether the previous image was painted.
- bool mPreviousImagePainted;
-
- // This is the image factory used by this container, layer managers using
- // this container can set an alternative image factory that will be used to
- // create images for this container.
- nsRefPtr<ImageFactory> mImageFactory;
-
- gfxIntSize mScaleHint;
-
- nsRefPtr<BufferRecycleBin> mRecycleBin;
-
- // This contains the remote image data for this container, if this is NULL
- // that means the container has no other process that may control its active
- // image.
- RemoteImageData *mRemoteData;
-
- // This cross-process mutex is used to synchronise access to mRemoteData.
- // When this mutex is held, we will always be inside the mReentrantMonitor
- // however the same is not true vice versa.
- CrossProcessMutex *mRemoteDataMutex;
-
- CompositionNotifySink *mCompositionNotifySink;
-
- // This member points to an ImageContainerChild if this ImageContainer was
- // sucessfully created with ENABLE_ASYNC, or points to null otherwise.
- // 'unsuccessful' in this case only means that the ImageContainerChild could not
- // be created, most likely because off-main-thread compositing is not enabled.
- // In this case the ImageContainer is perfectly usable, but it will forward
- // frames to the compositor through transactions in the main thread rather than
- // asynchronusly using the ImageBridge IPDL protocol.
- nsRefPtr<ImageContainerChild> mImageContainerChild;
-};
-
-class AutoLockImage
-{
-public:
- AutoLockImage(ImageContainer *aContainer) : mContainer(aContainer) { mImage = mContainer->LockCurrentImage(); }
- AutoLockImage(ImageContainer *aContainer, gfxASurface **aSurface) : mContainer(aContainer) {
- *aSurface = mContainer->LockCurrentAsSurface(&mSize, getter_AddRefs(mImage)).get();
- }
- ~AutoLockImage() { if (mContainer) { mContainer->UnlockCurrentImage(); } }
-
- Image* GetImage() { return mImage; }
- const gfxIntSize &GetSize() { return mSize; }
-
- void Unlock() {
- if (mContainer) {
- mImage = nullptr;
- mContainer->UnlockCurrentImage();
- mContainer = nullptr;
- }
- }
-
- /** Things get a little tricky here, because our underlying image can -still-
- * change, and OS X requires a complicated callback mechanism to update this
- * we need to support staying the lock and getting the new image in a proper
- * way. This method makes any images retrieved with GetImage invalid!
- */
- void Refresh() {
- if (mContainer) {
- mContainer->UnlockCurrentImage();
- mImage = mContainer->LockCurrentImage();
- }
- }
-
-private:
- ImageContainer *mContainer;
- nsRefPtr<Image> mImage;
- gfxIntSize mSize;
-};
+class ImageContainer;
/**
* A Layer which renders an Image.
*/
class THEBES_API ImageLayer : public Layer {
public:
enum ScaleMode {
SCALE_NONE,
@@ -656,20 +28,18 @@ public:
// Unimplemented - SCALE_PRESERVE_ASPECT_RATIO_CONTAIN
};
/**
* CONSTRUCTION PHASE ONLY
* Set the ImageContainer. aContainer must have the same layer manager
* as this layer.
*/
- void SetContainer(ImageContainer* aContainer)
- {
- mContainer = aContainer;
- }
+ void SetContainer(ImageContainer* aContainer);
+
/**
* CONSTRUCTION PHASE ONLY
* Set the filter used to resample this image if necessary.
*/
void SetFilter(gfxPattern::GraphicsFilter aFilter) { mFilter = aFilter; }
/**
* CONSTRUCTION PHASE ONLY
@@ -682,292 +52,36 @@ public:
}
ImageContainer* GetContainer() { return mContainer; }
gfxPattern::GraphicsFilter GetFilter() { return mFilter; }
MOZ_LAYER_DECL_NAME("ImageLayer", TYPE_IMAGE)
- virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface)
- {
- // Snap image edges to pixel boundaries
- gfxRect snap(0, 0, 0, 0);
- if (mContainer) {
- gfxIntSize size = mContainer->GetCurrentSize();
- snap.SizeTo(gfxSize(size.width, size.height));
- }
- // Snap our local transform first, and snap the inherited transform as well.
- // This makes our snapping equivalent to what would happen if our content
- // was drawn into a ThebesLayer (gfxContext would snap using the local
- // transform, then we'd snap again when compositing the ThebesLayer).
- mEffectiveTransform =
- SnapTransform(GetLocalTransform(), snap, nullptr)*
- SnapTransform(aTransformToSurface, gfxRect(0, 0, 0, 0), nullptr);
- ComputeEffectiveTransformForMaskLayer(aTransformToSurface);
- }
+ virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface);
/**
* if true, the image will only be backed by a single tile texture
*/
void SetForceSingleTile(bool aForceSingleTile)
{
mForceSingleTile = aForceSingleTile;
Mutated();
}
protected:
- ImageLayer(LayerManager* aManager, void* aImplData)
- : Layer(aManager, aImplData), mFilter(gfxPattern::FILTER_GOOD)
- , mScaleMode(SCALE_NONE), mForceSingleTile(false) {}
-
+ ImageLayer(LayerManager* aManager, void* aImplData);
+ ~ImageLayer();
virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix);
nsRefPtr<ImageContainer> mContainer;
gfxPattern::GraphicsFilter mFilter;
gfxIntSize mScaleToSize;
ScaleMode mScaleMode;
bool mForceSingleTile;
};
-/****** Image subtypes for the different formats ******/
-
-/**
- * We assume that the image data is in the REC 470M color space (see
- * Theora specification, section 4.3.1).
- *
- * The YCbCr format can be:
- *
- * 4:4:4 - CbCr width/height are the same as Y.
- * 4:2:2 - CbCr width is half that of Y. Height is the same.
- * 4:2:0 - CbCr width and height is half that of Y.
- *
- * The color format is detected based on the height/width ratios
- * defined above.
- *
- * The Image that is rendered is the picture region defined by
- * mPicX, mPicY and mPicSize. The size of the rendered image is
- * mPicSize, not mYSize or mCbCrSize.
- */
-class THEBES_API PlanarYCbCrImage : public Image {
-public:
- struct Data {
- // Luminance buffer
- PRUint8* mYChannel;
- PRInt32 mYStride;
- gfxIntSize mYSize;
- // Chroma buffers
- PRUint8* mCbChannel;
- PRUint8* mCrChannel;
- PRInt32 mCbCrStride;
- gfxIntSize mCbCrSize;
- // Picture region
- PRUint32 mPicX;
- PRUint32 mPicY;
- gfxIntSize mPicSize;
- StereoMode mStereoMode;
-
- nsIntRect GetPictureRect() const {
- return nsIntRect(mPicX, mPicY,
- mPicSize.width,
- mPicSize.height);
- }
- };
-
- enum {
- MAX_DIMENSION = 16384
- };
-
- ~PlanarYCbCrImage();
-
- /**
- * This makes a copy of the data buffers, in order to support functioning
- * in all different layer managers.
- */
- virtual void SetData(const Data& aData);
-
- /**
- * Ask this Image to not convert YUV to RGB during SetData, and make
- * the original data available through GetData. This is optional,
- * and not all PlanarYCbCrImages will support it.
- */
- virtual void SetDelayedConversion(bool aDelayed) { }
-
- /**
- * Grab the original YUV data. This is optional.
- */
- virtual const Data* GetData() { return &mData; }
-
- /**
- * Make a copy of the YCbCr data into local storage.
- *
- * @param aData Input image data.
- * @param aYOffset Pixels to skip between lines in the Y plane.
- * @param aYSkip Pixels to skip between pixels in the Y plane.
- * @param aCbOffset Pixels to skip between lines in the Cb plane.
- * @param aCbSkip Pixels to skip between pixels in the Cb plane.
- * @param aCrOffset Pixels to skip between lines in the Cr plane.
- * @param aCrSkip Pixels to skip between pixels in the Cr plane.
- */
- void CopyData(const Data& aData,
- PRInt32 aYOffset = 0, PRInt32 aYSkip = 0,
- PRInt32 aCbOffset = 0, PRInt32 aCbSkip = 0,
- PRInt32 aCrOffset = 0, PRInt32 aCrSkip = 0);
-
- /**
- * Return a buffer to store image data in.
- * The default implementation returns memory that can
- * be freed wit delete[]
- */
- virtual PRUint8* AllocateBuffer(PRUint32 aSize);
-
- /**
- * Return the number of bytes of heap memory used to store this image.
- */
- virtual PRUint32 GetDataSize() { return mBufferSize; }
-
- already_AddRefed<gfxASurface> GetAsSurface();
-
- virtual gfxIntSize GetSize() { return mSize; }
-
- void SetOffscreenFormat(gfxImageFormat aFormat) { mOffscreenFormat = aFormat; }
- gfxImageFormat GetOffscreenFormat() { return mOffscreenFormat; }
-
- // XXX - not easy to protect these sadly.
- nsAutoArrayPtr<PRUint8> mBuffer;
- PRUint32 mBufferSize;
- Data mData;
- gfxIntSize mSize;
- gfxImageFormat mOffscreenFormat;
- nsCountedRef<nsMainThreadSurfaceRef> mSurface;
- nsRefPtr<BufferRecycleBin> mRecycleBin;
-
- PlanarYCbCrImage(BufferRecycleBin *aRecycleBin);
-};
-
-/**
- * Currently, the data in a CairoImage surface is treated as being in the
- * device output color space. This class is very simple as all backends
- * have to know about how to deal with drawing a cairo image.
- */
-class THEBES_API CairoImage : public Image {
-public:
- struct Data {
- gfxASurface* mSurface;
- gfxIntSize mSize;
- };
-
- /**
- * This can only be called on the main thread. It may add a reference
- * to the surface (which will eventually be released on the main thread).
- * The surface must not be modified after this call!!!
- */
- void SetData(const Data& aData)
- {
- mSurface = aData.mSurface;
- mSize = aData.mSize;
- }
-
-
- virtual already_AddRefed<gfxASurface> GetAsSurface()
- {
- NS_ASSERTION(NS_IsMainThread(), "Must be main thread");
- nsRefPtr<gfxASurface> surface = mSurface.get();
- return surface.forget();
- }
-
- gfxIntSize GetSize() { return mSize; }
-
- CairoImage() : Image(NULL, CAIRO_SURFACE) {}
-
- nsCountedRef<nsMainThreadSurfaceRef> mSurface;
- gfxIntSize mSize;
-};
-
-#ifdef XP_MACOSX
-class THEBES_API MacIOSurfaceImage : public Image {
-public:
- struct Data {
- MacIOSurface* mIOSurface;
- };
-
- MacIOSurfaceImage()
- : Image(NULL, MAC_IO_SURFACE)
- , mSize(0, 0)
- , mPluginInstanceOwner(NULL)
- , mUpdateCallback(NULL)
- , mDestroyCallback(NULL)
- {}
-
- virtual ~MacIOSurfaceImage()
- {
- if (mDestroyCallback) {
- mDestroyCallback(mPluginInstanceOwner);
- }
- }
-
- /**
- * This can only be called on the main thread. It may add a reference
- * to the surface (which will eventually be released on the main thread).
- * The surface must not be modified after this call!!!
- */
- virtual void SetData(const Data& aData);
-
- /**
- * Temporary hacks to force plugin drawing during an empty transaction.
- * This should not be used for anything else, and will be removed
- * when async plugin rendering is complete.
- */
- typedef void (*UpdateSurfaceCallback)(ImageContainer* aContainer, void* aInstanceOwner);
- virtual void SetUpdateCallback(UpdateSurfaceCallback aCallback, void* aInstanceOwner)
- {
- mUpdateCallback = aCallback;
- mPluginInstanceOwner = aInstanceOwner;
- }
-
- typedef void (*DestroyCallback)(void* aInstanceOwner);
- virtual void SetDestroyCallback(DestroyCallback aCallback)
- {
- mDestroyCallback = aCallback;
- }
-
- virtual gfxIntSize GetSize()
- {
- return mSize;
- }
-
- MacIOSurface* GetIOSurface()
- {
- return mIOSurface;
- }
-
- void Update(ImageContainer* aContainer);
-
- virtual already_AddRefed<gfxASurface> GetAsSurface();
-
-private:
- gfxIntSize mSize;
- RefPtr<MacIOSurface> mIOSurface;
- void* mPluginInstanceOwner;
- UpdateSurfaceCallback mUpdateCallback;
- DestroyCallback mDestroyCallback;
-};
-#endif
-
-class RemoteBitmapImage : public Image {
-public:
- RemoteBitmapImage() : Image(NULL, REMOTE_IMAGE_BITMAP) {}
-
- already_AddRefed<gfxASurface> GetAsSurface();
-
- gfxIntSize GetSize() { return mSize; }
-
- unsigned char *mData;
- int mStride;
- gfxIntSize mSize;
- RemoteImageData::Format mFormat;
-};
-
}
}
#endif /* GFX_IMAGELAYER_H */
new file mode 100644
--- /dev/null
+++ b/gfx/layers/ImageTypes.h
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * 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 GFX_IMAGETYPES_H
+#define GFX_IMAGETYPES_H
+
+namespace mozilla {
+
+enum ImageFormat {
+ /**
+ * The PLANAR_YCBCR format creates a PlanarYCbCrImage. All backends should
+ * support this format, because the Ogg video decoder depends on it.
+ * The maximum image width and height is 16384.
+ */
+ PLANAR_YCBCR,
+
+ /**
+ * The CAIRO_SURFACE format creates a CairoImage. All backends should
+ * support this format, because video rendering sometimes requires it.
+ *
+ * This format is useful even though a ThebesLayer could be used.
+ * It makes it easy to render a cairo surface when another Image format
+ * could be used. It can also avoid copying the surface data in some
+ * cases.
+ *
+ * Images in CAIRO_SURFACE format should only be created and
+ * manipulated on the main thread, since the underlying cairo surface
+ * is main-thread-only.
+ */
+ CAIRO_SURFACE,
+
+ /**
+ * The MAC_IO_SURFACE format creates a MacIOSurfaceImage.
+ *
+ * It wraps an IOSurface object and binds it directly to a GL texture.
+ */
+ MAC_IO_SURFACE,
+
+ /**
+ * The GONK_IO_SURFACE format creates a GonkIOSurfaceImage.
+ *
+ * It wraps an GraphicBuffer object and binds it directly to a GL texture.
+ */
+ GONK_IO_SURFACE,
+
+ /**
+ * An bitmap image that can be shared with a remote process.
+ */
+ REMOTE_IMAGE_BITMAP,
+
+ /**
+ * A OpenGL texture that can be shared across threads or processes
+ */
+ SHARED_TEXTURE,
+
+ /**
+ * An DXGI shared surface handle that can be shared with a remote process.
+ */
+ REMOTE_IMAGE_DXGI_TEXTURE
+};
+
+
+enum StereoMode {
+ STEREO_MODE_MONO,
+ STEREO_MODE_LEFT_RIGHT,
+ STEREO_MODE_RIGHT_LEFT,
+ STEREO_MODE_BOTTOM_TOP,
+ STEREO_MODE_TOP_BOTTOM
+};
+
+
+} // namespace
+
+#endif
\ No newline at end of file
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -2,19 +2,19 @@
* vim: sw=2 ts=8 et :
*/
/* 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 "mozilla/layers/PLayers.h"
#include "mozilla/layers/ShadowLayers.h"
-#include "mozilla/layers/ImageBridgeChild.h" // TODO: temp
#include "ImageLayers.h"
+#include "ImageContainer.h"
#include "Layers.h"
#include "gfxPlatform.h"
#include "ReadbackLayer.h"
#include "gfxUtils.h"
#include "nsPrintfCString.h"
#include "mozilla/Util.h"
#include "LayerSorter.h"
#include "AnimationCommon.h"
--- a/gfx/layers/Makefile.in
+++ b/gfx/layers/Makefile.in
@@ -29,17 +29,19 @@ endif
EXPORTS = \
BasicLayers.h \
BasicTiledThebesLayer.h \
BasicImplData.h \
GonkIOSurfaceImage.h \
FrameMetrics.h \
CompositorParent.h \
+ ImageContainer.h \
ImageLayers.h \
+ ImageTypes.h \
Layers.h \
LayersTypes.h \
LayerManagerOGLShaders.h \
LayerManagerOGL.h \
LayerManagerOGLProgram.h \
LayerSorter.h \
ReadbackLayer.h \
ShadowLayersManager.h \
@@ -53,16 +55,17 @@ CPPSRCS = \
BasicCanvasLayer.cpp \
BasicColorLayer.cpp \
BasicContainerLayer.cpp \
BasicImageLayer.cpp \
BasicLayersImpl.cpp \
BasicThebesLayer.cpp \
BasicBuffers.cpp \
BasicTiledThebesLayer.cpp \
+ ImageContainer.cpp \
Layers.cpp \
RenderTrace.cpp \
ReadbackProcessor.cpp \
ThebesLayerBuffer.cpp \
CanvasLayerOGL.cpp \
ColorLayerOGL.cpp \
ContainerLayerOGL.cpp \
ImageLayerOGL.cpp \
--- a/gfx/layers/SharedTextureImage.h
+++ b/gfx/layers/SharedTextureImage.h
@@ -1,17 +1,17 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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 GFX_SHAREDTEXTUREIMAGE_H
#define GFX_SHAREDTEXTUREIMAGE_H
-#include "ImageLayers.h"
+#include "ImageContainer.h"
#include "GLContext.h"
// Split into a separate header from ImageLayers.h due to GLContext.h dependence
// Implementation remains in ImageLayers.cpp
namespace mozilla {
namespace layers {
--- a/gfx/layers/basic/BasicCanvasLayer.cpp
+++ b/gfx/layers/basic/BasicCanvasLayer.cpp
@@ -2,16 +2,17 @@
* 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 "mozilla/layers/PLayersParent.h"
#include "gfxImageSurface.h"
#include "GLContext.h"
#include "gfxUtils.h"
+#include "gfxPlatform.h"
#include "BasicLayersImpl.h"
#include "nsXULAppAPI.h"
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
--- a/gfx/layers/basic/BasicImageLayer.cpp
+++ b/gfx/layers/basic/BasicImageLayer.cpp
@@ -276,28 +276,28 @@ BasicShadowableImageLayer::Paint(gfxCont
return;
}
if (aMaskLayer) {
static_cast<BasicImplData*>(aMaskLayer->ImplData())
->Paint(aContext, nullptr);
}
- if (image->GetFormat() == Image::SHARED_TEXTURE &&
+ if (image->GetFormat() == ImageFormat::SHARED_TEXTURE &&
BasicManager()->GetParentBackendType() == mozilla::layers::LAYERS_OPENGL) {
SharedTextureImage *sharedImage = static_cast<SharedTextureImage*>(image);
const SharedTextureImage::Data *data = sharedImage->GetData();
SharedTextureDescriptor texture(data->mShareType, data->mHandle, data->mSize, data->mInverted);
SurfaceDescriptor descriptor(texture);
BasicManager()->PaintedImage(BasicManager()->Hold(this), descriptor);
return;
}
- if (image->GetFormat() == Image::PLANAR_YCBCR && BasicManager()->IsCompositingCheap()) {
+ if (image->GetFormat() == ImageFormat::PLANAR_YCBCR && BasicManager()->IsCompositingCheap()) {
PlanarYCbCrImage *YCbCrImage = static_cast<PlanarYCbCrImage*>(image);
const PlanarYCbCrImage::Data *data = YCbCrImage->GetData();
NS_ASSERTION(data, "Must be able to retrieve yuv data from image!");
if (mSize != data->mYSize || mCbCrSize != data->mCbCrSize || !IsSurfaceDescriptorValid(mBackBufferY)) {
DestroyBackBuffer();
mSize = data->mYSize;
mCbCrSize = data->mCbCrSize;
--- a/gfx/layers/basic/BasicImages.cpp
+++ b/gfx/layers/basic/BasicImages.cpp
@@ -52,27 +52,27 @@ private:
nsAutoArrayPtr<PRUint8> mDecodedBuffer;
};
class BasicImageFactory : public ImageFactory
{
public:
BasicImageFactory() {}
- virtual already_AddRefed<Image> CreateImage(const Image::Format* aFormats,
+ virtual already_AddRefed<Image> CreateImage(const ImageFormat* aFormats,
PRUint32 aNumFormats,
const gfxIntSize &aScaleHint,
BufferRecycleBin *aRecycleBin)
{
if (!aNumFormats) {
return nullptr;
}
nsRefPtr<Image> image;
- if (aFormats[0] == Image::PLANAR_YCBCR) {
+ if (aFormats[0] == ImageFormat::PLANAR_YCBCR) {
image = new BasicPlanarYCbCrImage(aScaleHint, gfxPlatform::GetPlatform()->GetOffscreenFormat(), aRecycleBin);
return image.forget();
}
return ImageFactory::CreateImage(aFormats, aNumFormats, aScaleHint, aRecycleBin);
}
};
--- a/gfx/layers/basic/BasicLayerManager.cpp
+++ b/gfx/layers/basic/BasicLayerManager.cpp
@@ -5,16 +5,17 @@
#include "mozilla/layers/PLayerChild.h"
#include "mozilla/layers/PLayersChild.h"
#include "mozilla/layers/PLayersParent.h"
#include "gfxSharedImageSurface.h"
#include "gfxImageSurface.h"
#include "gfxUtils.h"
+#include "gfxPlatform.h"
#include "nsXULAppAPI.h"
#include "RenderTrace.h"
#include "sampler.h"
#define PIXMAN_DONT_DEFINE_STDINT
#include "pixman.h"
#include "BasicTiledThebesLayer.h"
--- a/gfx/layers/basic/BasicLayers.h
+++ b/gfx/layers/basic/BasicLayers.h
@@ -22,16 +22,17 @@ namespace layers {
class BasicShadowableLayer;
class ShadowThebesLayer;
class ShadowContainerLayer;
class ShadowImageLayer;
class ShadowCanvasLayer;
class ShadowColorLayer;
class ReadbackProcessor;
+class ImageFactory;
/**
* This is a cairo/Thebes-only, main-thread-only implementation of layers.
*
* In each transaction, the client sets up the layer tree and then during
* the drawing phase, each ThebesLayer is painted directly into the target
* context (with appropriate clipping and Push/PopGroups performed
* between layers).
--- a/gfx/layers/basic/BasicTiledThebesLayer.cpp
+++ b/gfx/layers/basic/BasicTiledThebesLayer.cpp
@@ -1,16 +1,17 @@
/* 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 "mozilla/layers/PLayersChild.h"
#include "BasicTiledThebesLayer.h"
#include "gfxImageSurface.h"
#include "sampler.h"
+#include "gfxPlatform.h"
#ifdef GFX_TILEDLAYER_DEBUG_OVERLAY
#include "cairo.h"
#include <sstream>
using mozilla::layers::Layer;
static void DrawDebugOverlay(gfxImageSurface* imgSurf, int x, int y)
{
gfxContext c(imgSurf);
--- a/gfx/layers/d3d10/ImageLayerD3D10.cpp
+++ b/gfx/layers/d3d10/ImageLayerD3D10.cpp
@@ -91,39 +91,39 @@ ImageLayerD3D10::GetLayer()
* If successful, aHasAlpha will be true iff the resulting texture
* has an alpha component.
*/
ID3D10ShaderResourceView*
ImageLayerD3D10::GetImageSRView(Image* aImage, bool& aHasAlpha, IDXGIKeyedMutex **aMutex)
{
NS_ASSERTION(aImage, "Null image.");
- if (aImage->GetFormat() == Image::REMOTE_IMAGE_BITMAP) {
+ if (aImage->GetFormat() == ImageFormat::REMOTE_IMAGE_BITMAP) {
RemoteBitmapImage *remoteImage =
static_cast<RemoteBitmapImage*>(aImage);
if (!aImage->GetBackendData(mozilla::layers::LAYERS_D3D10)) {
nsAutoPtr<TextureD3D10BackendData> dat(new TextureD3D10BackendData());
dat->mTexture = DataToTexture(device(), remoteImage->mData, remoteImage->mStride, remoteImage->mSize);
if (dat->mTexture) {
device()->CreateShaderResourceView(dat->mTexture, NULL, getter_AddRefs(dat->mSRView));
aImage->SetBackendData(mozilla::layers::LAYERS_D3D10, dat.forget());
}
}
aHasAlpha = remoteImage->mFormat == RemoteImageData::BGRA32;
- } else if (aImage->GetFormat() == Image::REMOTE_IMAGE_DXGI_TEXTURE) {
+ } else if (aImage->GetFormat() == ImageFormat::REMOTE_IMAGE_DXGI_TEXTURE) {
RemoteDXGITextureImage *remoteImage =
static_cast<RemoteDXGITextureImage*>(aImage);
remoteImage->GetD3D10TextureBackendData(device());
aHasAlpha = remoteImage->mFormat == RemoteImageData::BGRA32;
- } else if (aImage->GetFormat() == Image::CAIRO_SURFACE) {
+ } else if (aImage->GetFormat() == ImageFormat::CAIRO_SURFACE) {
CairoImage *cairoImage =
static_cast<CairoImage*>(aImage);
if (!cairoImage->mSurface) {
return nullptr;
}
if (!aImage->GetBackendData(mozilla::layers::LAYERS_D3D10)) {
@@ -183,20 +183,20 @@ ImageLayerD3D10::RenderLayer()
gfxIntSize size = mScaleMode == SCALE_NONE ? image->GetSize() : mScaleToSize;
SetEffectTransformAndOpacity();
ID3D10EffectTechnique *technique;
nsRefPtr<IDXGIKeyedMutex> keyedMutex;
- if (image->GetFormat() == Image::CAIRO_SURFACE || image->GetFormat() == Image::REMOTE_IMAGE_BITMAP ||
- image->GetFormat() == Image::REMOTE_IMAGE_DXGI_TEXTURE)
+ if (image->GetFormat() == ImageFormat::CAIRO_SURFACE || image->GetFormat() == ImageFormat::REMOTE_IMAGE_BITMAP ||
+ image->GetFormat() == ImageFormat::REMOTE_IMAGE_DXGI_TEXTURE)
{
- NS_ASSERTION(image->GetFormat() != Image::CAIRO_SURFACE ||
+ NS_ASSERTION(image->GetFormat() != ImageFormat::CAIRO_SURFACE ||
!static_cast<CairoImage*>(image)->mSurface ||
static_cast<CairoImage*>(image)->mSurface->GetContentType() != gfxASurface::CONTENT_ALPHA,
"Image layer has alpha image");
bool hasAlpha = false;
nsRefPtr<ID3D10ShaderResourceView> srView = GetImageSRView(image, hasAlpha, getter_AddRefs(keyedMutex));
if (!srView) {
return;
@@ -215,17 +215,17 @@ ImageLayerD3D10::RenderLayer()
effect()->GetVariableByName("vLayerQuad")->AsVector()->SetFloatVector(
ShaderConstantRectD3D10(
(float)0,
(float)0,
(float)size.width,
(float)size.height)
);
- } else if (image->GetFormat() == Image::PLANAR_YCBCR) {
+ } else if (image->GetFormat() == ImageFormat::PLANAR_YCBCR) {
PlanarYCbCrImage *yuvImage =
static_cast<PlanarYCbCrImage*>(image);
if (!yuvImage->mBufferSize) {
return;
}
if (!yuvImage->GetBackendData(mozilla::layers::LAYERS_D3D10)) {
@@ -301,17 +301,17 @@ ImageLayerD3D10::RenderLayer()
ShaderConstantRectD3D10(
(float)yuvImage->mData.mPicX / yuvImage->mData.mYSize.width,
(float)yuvImage->mData.mPicY / yuvImage->mData.mYSize.height,
(float)yuvImage->mData.mPicSize.width / yuvImage->mData.mYSize.width,
(float)yuvImage->mData.mPicSize.height / yuvImage->mData.mYSize.height)
);
}
- bool resetTexCoords = image->GetFormat() == Image::PLANAR_YCBCR;
+ bool resetTexCoords = image->GetFormat() == ImageFormat::PLANAR_YCBCR;
image = nullptr;
autoLock.Unlock();
technique->GetPassByIndex(0)->Apply(0);
device()->Draw(4, 0);
if (keyedMutex) {
keyedMutex->ReleaseSync(0);
@@ -379,17 +379,17 @@ ImageLayerD3D10::GetAsTexture(gfxIntSize
AutoLockImage autoLock(GetContainer());
Image *image = autoLock.GetImage();
if (!image) {
return nullptr;
}
- if (image->GetFormat() != Image::CAIRO_SURFACE) {
+ if (image->GetFormat() != ImageFormat::CAIRO_SURFACE) {
return nullptr;
}
*aSize = image->GetSize();
bool dontCare;
nsRefPtr<ID3D10ShaderResourceView> result = GetImageSRView(image, dontCare);
return result.forget();
}
--- a/gfx/layers/d3d10/ImageLayerD3D10.h
+++ b/gfx/layers/d3d10/ImageLayerD3D10.h
@@ -3,16 +3,17 @@
* 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 GFX_IMAGELAYERD3D10_H
#define GFX_IMAGELAYERD3D10_H
#include "LayerManagerD3D10.h"
#include "ImageLayers.h"
+#include "ImageContainer.h"
#include "yuv_convert.h"
namespace mozilla {
namespace layers {
class THEBES_API ImageLayerD3D10 : public ImageLayer,
public LayerD3D10
{
--- a/gfx/layers/d3d9/ImageLayerD3D9.cpp
+++ b/gfx/layers/d3d9/ImageLayerD3D9.cpp
@@ -295,30 +295,30 @@ ImageLayerD3D9::GetLayer()
* If successful, aHasAlpha will be set to true if the texture has an
* alpha component, false otherwise.
*/
IDirect3DTexture9*
ImageLayerD3D9::GetTexture(Image *aImage, bool& aHasAlpha)
{
NS_ASSERTION(aImage, "Null image.");
- if (aImage->GetFormat() == Image::REMOTE_IMAGE_BITMAP) {
+ if (aImage->GetFormat() == ImageFormat::REMOTE_IMAGE_BITMAP) {
RemoteBitmapImage *remoteImage =
static_cast<RemoteBitmapImage*>(aImage);
if (!aImage->GetBackendData(mozilla::layers::LAYERS_D3D9)) {
nsAutoPtr<TextureD3D9BackendData> dat(new TextureD3D9BackendData());
dat->mTexture = DataToTexture(device(), remoteImage->mData, remoteImage->mStride, remoteImage->mSize, D3DFMT_A8R8G8B8);
if (dat->mTexture) {
aImage->SetBackendData(mozilla::layers::LAYERS_D3D9, dat.forget());
}
}
aHasAlpha = remoteImage->mFormat == RemoteImageData::BGRA32;
- } else if (aImage->GetFormat() == Image::CAIRO_SURFACE) {
+ } else if (aImage->GetFormat() == ImageFormat::CAIRO_SURFACE) {
CairoImage *cairoImage =
static_cast<CairoImage*>(aImage);
if (!cairoImage->mSurface) {
return nullptr;
}
if (!aImage->GetBackendData(mozilla::layers::LAYERS_D3D9)) {
@@ -365,20 +365,20 @@ ImageLayerD3D9::RenderLayer()
if (!image) {
return;
}
SetShaderTransformAndOpacity();
gfxIntSize size = mScaleMode == SCALE_NONE ? image->GetSize() : mScaleToSize;
- if (image->GetFormat() == Image::CAIRO_SURFACE ||
- image->GetFormat() == Image::REMOTE_IMAGE_BITMAP)
+ if (image->GetFormat() == ImageFormat::CAIRO_SURFACE ||
+ image->GetFormat() == ImageFormat::REMOTE_IMAGE_BITMAP)
{
- NS_ASSERTION(image->GetFormat() != Image::CAIRO_SURFACE ||
+ NS_ASSERTION(image->GetFormat() != ImageFormat::CAIRO_SURFACE ||
!static_cast<CairoImage*>(image)->mSurface ||
static_cast<CairoImage*>(image)->mSurface->GetContentType() != gfxASurface::CONTENT_ALPHA,
"Image layer has alpha image");
bool hasAlpha = false;
nsRefPtr<IDirect3DTexture9> texture = GetTexture(image, hasAlpha);
device()->SetVertexShaderConstantF(CBvLayerQuad,
@@ -517,18 +517,18 @@ ImageLayerD3D9::GetAsTexture(gfxIntSize*
AutoLockImage autoLock(GetContainer());
Image *image = autoLock.GetImage();
if (!image) {
return nullptr;
}
- if (image->GetFormat() != Image::CAIRO_SURFACE &&
- image->GetFormat() != Image::REMOTE_IMAGE_BITMAP) {
+ if (image->GetFormat() != ImageFormat::CAIRO_SURFACE &&
+ image->GetFormat() != ImageFormat::REMOTE_IMAGE_BITMAP) {
return nullptr;
}
bool dontCare;
*aSize = image->GetSize();
nsRefPtr<IDirect3DTexture9> result = GetTexture(image, dontCare);
return result.forget();
}
--- a/gfx/layers/d3d9/ImageLayerD3D9.h
+++ b/gfx/layers/d3d9/ImageLayerD3D9.h
@@ -3,16 +3,17 @@
* 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 GFX_IMAGELAYERD3D9_H
#define GFX_IMAGELAYERD3D9_H
#include "LayerManagerD3D9.h"
#include "ImageLayers.h"
+#include "ImageContainer.h"
#include "yuv_convert.h"
namespace mozilla {
namespace layers {
class ShadowBufferD3D9;
class THEBES_API ImageLayerD3D9 : public ImageLayer,
--- a/gfx/layers/ipc/ImageContainerChild.cpp
+++ b/gfx/layers/ipc/ImageContainerChild.cpp
@@ -4,17 +4,17 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ImageContainerChild.h"
#include "gfxSharedImageSurface.h"
#include "ShadowLayers.h"
#include "mozilla/layers/PLayers.h"
#include "mozilla/layers/SharedImageUtils.h"
-#include "ImageLayers.h"
+#include "ImageContainer.h"
#include "GonkIOSurfaceImage.h"
namespace mozilla {
namespace layers {
/*
* - POOL_MAX_SHARED_IMAGES is the maximum number number of shared images to
* store in the ImageContainerChild's pool.
@@ -116,17 +116,17 @@ void ImageContainerChild::DestroySharedI
"Should be in ImageBridgeChild thread.");
--mActiveImageCount;
DeallocSharedImageData(this, aImage);
}
bool ImageContainerChild::CopyDataIntoSharedImage(Image* src, SharedImage* dest)
{
- if ((src->GetFormat() == Image::PLANAR_YCBCR) &&
+ if ((src->GetFormat() == ImageFormat::PLANAR_YCBCR) &&
(dest->type() == SharedImage::TYUVImage)) {
PlanarYCbCrImage *YCbCrImage = static_cast<PlanarYCbCrImage*>(src);
const PlanarYCbCrImage::Data *data = YCbCrImage->GetData();
NS_ASSERTION(data, "Must be able to retrieve yuv data from image!");
YUVImage& yuv = dest->get_YUVImage();
nsRefPtr<gfxSharedImageSurface> surfY =
gfxSharedImageSurface::Open(yuv.Ydata());
@@ -156,17 +156,17 @@ bool ImageContainerChild::CopyDataIntoSh
SharedImage* ImageContainerChild::CreateSharedImageFromData(Image* image)
{
NS_ABORT_IF_FALSE(InImageBridgeChildThread(),
"Should be in ImageBridgeChild thread.");
++mActiveImageCount;
- if (image->GetFormat() == Image::PLANAR_YCBCR ) {
+ if (image->GetFormat() == ImageFormat::PLANAR_YCBCR ) {
PlanarYCbCrImage *YCbCrImage = static_cast<PlanarYCbCrImage*>(image);
const PlanarYCbCrImage::Data *data = YCbCrImage->GetData();
NS_ASSERTION(data, "Must be able to retrieve yuv data from image!");
nsRefPtr<gfxSharedImageSurface> tempBufferY;
nsRefPtr<gfxSharedImageSurface> tempBufferU;
nsRefPtr<gfxSharedImageSurface> tempBufferV;
@@ -197,17 +197,17 @@ SharedImage* ImageContainerChild::Create
YUVImage(tempBufferY->GetShmem(),
tempBufferU->GetShmem(),
tempBufferV->GetShmem(),
data->GetPictureRect()));
NS_ABORT_IF_FALSE(result->type() == SharedImage::TYUVImage,
"SharedImage type not set correctly");
return result;
#ifdef MOZ_WIDGET_GONK
- } else if (image->GetFormat() == Image::GONK_IO_SURFACE) {
+ } else if (image->GetFormat() == ImageFormat::GONK_IO_SURFACE) {
GonkIOSurfaceImage* gonkImage = static_cast<GonkIOSurfaceImage*>(image);
SharedImage* result = new SharedImage(gonkImage->GetSurfaceDescriptor());
return result;
#endif
} else {
NS_RUNTIMEABORT("TODO: Only YUVImage is supported here right now.");
}
return nullptr;
@@ -231,17 +231,17 @@ bool ImageContainerChild::AddSharedImage
return false; // TODO accept more image formats in the pool
}
static bool
SharedImageCompatibleWith(SharedImage* aSharedImage, Image* aImage)
{
// TODO accept more image formats
switch (aImage->GetFormat()) {
- case Image::PLANAR_YCBCR: {
+ case ImageFormat::PLANAR_YCBCR: {
if (aSharedImage->type() != SharedImage::TYUVImage) {
return false;
}
const PlanarYCbCrImage::Data* data =
static_cast<PlanarYCbCrImage*>(aImage)->GetData();
const YUVImage& yuv = aSharedImage->get_YUVImage();
nsRefPtr<gfxSharedImageSurface> surfY =
--- a/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp
+++ b/gfx/layers/ipc/ShadowLayerUtilsGralloc.cpp
@@ -10,16 +10,17 @@
#include "mozilla/layers/PLayersChild.h"
#include "mozilla/layers/ShadowLayers.h"
#include "mozilla/unused.h"
#include "nsXULAppAPI.h"
#include "ShadowLayerUtilsGralloc.h"
#include "gfxImageSurface.h"
+#include "gfxPlatform.h"
#include "sampler.h"
using namespace android;
using namespace base;
using namespace mozilla::layers;
namespace IPC {
--- a/gfx/layers/ipc/ShadowLayersParent.cpp
+++ b/gfx/layers/ipc/ShadowLayersParent.cpp
@@ -14,16 +14,17 @@
#include "mozilla/layout/RenderFrameParent.h"
#include "mozilla/unused.h"
#include "RenderTrace.h"
#include "ShadowLayerParent.h"
#include "ShadowLayersParent.h"
#include "ShadowLayers.h"
#include "ShadowLayerUtils.h"
#include "TiledLayerBuffer.h"
+#include "gfxPlatform.h"
typedef std::vector<mozilla::layers::EditReply> EditReplyVector;
using mozilla::layout::RenderFrameParent;
namespace mozilla {
namespace layers {
--- a/gfx/layers/opengl/CanvasLayerOGL.cpp
+++ b/gfx/layers/opengl/CanvasLayerOGL.cpp
@@ -11,16 +11,20 @@
#include "CanvasLayerOGL.h"
#include "gfxImageSurface.h"
#include "gfxContext.h"
#include "GLContextProvider.h"
#include "gfxPlatform.h"
+#ifdef XP_MACOSX
+#include "mozilla/gfx/MacIOSurface.h"
+#endif
+
#ifdef XP_WIN
#include "gfxWindowsSurface.h"
#include "WGLLibrary.h"
#endif
#ifdef XP_MACOSX
#include <OpenGL/OpenGL.h>
#endif
--- a/gfx/layers/opengl/CanvasLayerOGL.h
+++ b/gfx/layers/opengl/CanvasLayerOGL.h
@@ -61,19 +61,20 @@ protected:
bool mGLBufferIsPremultiplied;
bool mNeedsYFlip;
#if defined(MOZ_WIDGET_GTK2) && !defined(MOZ_PLATFORM_MAEMO)
GLXPixmap mPixmap;
#endif
nsRefPtr<gfxImageSurface> mCachedTempSurface;
gfxIntSize mCachedSize;
- gfxImageFormat mCachedFormat;
+ gfxASurface::gfxImageFormat mCachedFormat;
- gfxImageSurface* GetTempSurface(const gfxIntSize& aSize, const gfxImageFormat aFormat)
+ gfxImageSurface* GetTempSurface(const gfxIntSize& aSize,
+ const gfxASurface::gfxImageFormat aFormat)
{
if (!mCachedTempSurface ||
aSize.width != mCachedSize.width ||
aSize.height != mCachedSize.height ||
aFormat != mCachedFormat)
{
mCachedTempSurface = new gfxImageSurface(aSize, aFormat);
mCachedSize = aSize;
--- a/gfx/layers/opengl/ImageLayerOGL.cpp
+++ b/gfx/layers/opengl/ImageLayerOGL.cpp
@@ -1,16 +1,17 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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 "gfxSharedImageSurface.h"
#include "mozilla/layers/ImageContainerParent.h"
+#include "ImageContainer.h" // for PlanarYCBCRImage
#include "ipc/AutoOpenSurface.h"
#include "ImageLayerOGL.h"
#include "gfxImageSurface.h"
#include "gfxUtils.h"
#include "yuv_convert.h"
#include "GLContextProvider.h"
#if defined(MOZ_WIDGET_GTK2) && !defined(MOZ_PLATFORM_MAEMO)
# include "GLXLibrary.h"
@@ -238,22 +239,22 @@ ImageLayerOGL::RenderLayer(int,
AutoLockImage autoLock(container);
Image *image = autoLock.GetImage();
if (!image) {
return;
}
- NS_ASSERTION(image->GetFormat() != Image::REMOTE_IMAGE_BITMAP,
+ NS_ASSERTION(image->GetFormat() != ImageFormat::REMOTE_IMAGE_BITMAP,
"Remote images aren't handled yet in OGL layers!");
NS_ASSERTION(mScaleMode == SCALE_NONE,
"Scale modes other than none not handled yet in OGL layers!");
- if (image->GetFormat() == Image::PLANAR_YCBCR) {
+ if (image->GetFormat() == ImageFormat::PLANAR_YCBCR) {
PlanarYCbCrImage *yuvImage =
static_cast<PlanarYCbCrImage*>(image);
if (!yuvImage->mBufferSize) {
return;
}
PlanarYCbCrOGLBackendData *data =
@@ -303,17 +304,17 @@ ImageLayerOGL::RenderLayer(int,
mOGLManager->BindAndDrawQuadWithTextureRect(program,
yuvImage->mData.GetPictureRect(),
nsIntSize(yuvImage->mData.mYSize.width,
yuvImage->mData.mYSize.height));
// We shouldn't need to do this, but do it anyway just in case
// someone else forgets.
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
- } else if (image->GetFormat() == Image::CAIRO_SURFACE) {
+ } else if (image->GetFormat() == ImageFormat::CAIRO_SURFACE) {
CairoImage *cairoImage =
static_cast<CairoImage*>(image);
if (!cairoImage->mSurface) {
return;
}
NS_ASSERTION(cairoImage->mSurface->GetContentType() != gfxASurface::CONTENT_ALPHA,
@@ -379,17 +380,17 @@ ImageLayerOGL::RenderLayer(int,
#if defined(MOZ_WIDGET_GTK2) && !defined(MOZ_PLATFORM_MAEMO)
if (cairoImage->mSurface && pixmap) {
sGLXLibrary.ReleaseTexImage(pixmap);
sGLXLibrary.DestroyPixmap(pixmap);
}
#endif
#ifdef XP_MACOSX
- } else if (image->GetFormat() == Image::MAC_IO_SURFACE) {
+ } else if (image->GetFormat() == ImageFormat::MAC_IO_SURFACE) {
MacIOSurfaceImage *ioImage =
static_cast<MacIOSurfaceImage*>(image);
if (!mOGLManager->GetThebesLayerCallback()) {
// If its an empty transaction we still need to update
// the plugin IO Surface and make sure we grab the
// new image
ioImage->Update(GetContainer());
@@ -435,17 +436,17 @@ ImageLayerOGL::RenderLayer(int,
program->SetRenderOffset(aOffset);
program->SetTextureUnit(0);
program->LoadMask(GetMaskLayer());
mOGLManager->BindAndDrawQuad(program);
gl()->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, 0);
#endif
#ifdef MOZ_WIDGET_GONK
- } else if (image->GetFormat() == Image::GONK_IO_SURFACE) {
+ } else if (image->GetFormat() == ImageFormat::GONK_IO_SURFACE) {
GonkIOSurfaceImage *ioImage = static_cast<GonkIOSurfaceImage*>(image);
if (!ioImage) {
return;
}
gl()->MakeCurrent();
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
@@ -630,17 +631,17 @@ ImageLayerOGL::LoadAsTexture(GLuint aTex
AutoLockImage autoLock(GetContainer());
Image *image = autoLock.GetImage();
if (!image) {
return false;
}
- if (image->GetFormat() != Image::CAIRO_SURFACE) {
+ if (image->GetFormat() != ImageFormat::CAIRO_SURFACE) {
return false;
}
CairoImage* cairoImage = static_cast<CairoImage*>(image);
if (!cairoImage->mSurface) {
return false;
}
--- a/gfx/layers/opengl/ImageLayerOGL.h
+++ b/gfx/layers/opengl/ImageLayerOGL.h
@@ -6,22 +6,26 @@
#ifndef GFX_IMAGELAYEROGL_H
#define GFX_IMAGELAYEROGL_H
#include "mozilla/layers/PLayers.h"
#include "mozilla/layers/ShadowLayers.h"
#include "LayerManagerOGL.h"
#include "ImageLayers.h"
+#include "ImageContainer.h"
#include "yuv_convert.h"
#include "mozilla/Mutex.h"
namespace mozilla {
namespace layers {
+class CairoImage;
+class PlanarYCbCrImage;
+
/**
* This class wraps a GL texture. It includes a GLContext reference
* so we can use to free the texture when destroyed. The implementation
* makes sure to always free the texture on the main thread, even if the
* destructor runs on another thread.
*
* We ensure that the GLContext reference is only addrefed and released
* on the main thread, although it uses threadsafe recounting so we don't
--- a/gfx/thebes/gfxUtils.h
+++ b/gfx/thebes/gfxUtils.h
@@ -4,17 +4,17 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef GFX_UTILS_H
#define GFX_UTILS_H
#include "gfxTypes.h"
#include "gfxPattern.h"
#include "gfxImageSurface.h"
-#include "ImageLayers.h"
+#include "ImageContainer.h"
#include "mozilla/gfx/2D.h"
#include "imgIContainer.h"
class gfxDrawable;
class nsIntRegion;
struct nsIntRect;
class THEBES_API gfxUtils {
--- a/image/src/RasterImage.cpp
+++ b/image/src/RasterImage.cpp
@@ -12,17 +12,18 @@
#include "RasterImage.h"
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsAutoPtr.h"
#include "nsStringStream.h"
#include "prmem.h"
#include "prenv.h"
#include "ImageLogging.h"
-#include "ImageLayers.h"
+#include "ImageContainer.h"
+#include "Layers.h"
#include "nsPNGDecoder.h"
#include "nsGIFDecoder2.h"
#include "nsJPEGDecoder.h"
#include "nsBMPDecoder.h"
#include "nsICODecoder.h"
#include "nsIconDecoder.h"
@@ -877,17 +878,17 @@ RasterImage::GetImageContainer(ImageCont
cairoData.mSurface = imageSurface;
GetWidth(&cairoData.mSize.width);
GetHeight(&cairoData.mSize.height);
mImageContainer = LayerManager::CreateImageContainer();
// Now create a CairoImage to display the surface.
- layers::Image::Format cairoFormat = layers::Image::CAIRO_SURFACE;
+ ImageFormat cairoFormat = ImageFormat::CAIRO_SURFACE;
nsRefPtr<layers::Image> image = mImageContainer->CreateImage(&cairoFormat, 1);
NS_ASSERTION(image, "Failed to create Image");
NS_ASSERTION(image->GetFormat() == cairoFormat, "Wrong format");
static_cast<CairoImage*>(image.get())->SetData(cairoData);
mImageContainer->SetCurrentImageInTransaction(image);
*_retval = mImageContainer;
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -3183,17 +3183,17 @@ ContainerState::SetupMaskLayer(Layer *aL
// paint the clipping rects with alpha to create the mask
context->SetColor(gfxRGBA(1, 1, 1, 1));
aClip.DrawRoundedRectsTo(context, A2D, 0, aRoundedRectClipCount);
// build the image and container
container = aLayer->Manager()->CreateImageContainer();
NS_ASSERTION(container, "Could not create image container for mask layer.");
- static const Image::Format format = Image::CAIRO_SURFACE;
+ static const ImageFormat format = ImageFormat::CAIRO_SURFACE;
nsRefPtr<Image> image = container->CreateImage(&format, 1);
NS_ASSERTION(image, "Could not create image container for mask layer.");
CairoImage::Data data;
data.mSurface = surface;
data.mSize = surfaceSize;
static_cast<CairoImage*>(image.get())->SetData(data);
container->SetCurrentImageInTransaction(image);
--- a/layout/base/MaskLayerImageCache.cpp
+++ b/layout/base/MaskLayerImageCache.cpp
@@ -1,19 +1,28 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* 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 "MaskLayerImageCache.h"
+#include "ImageContainer.h"
using namespace mozilla::layers;
namespace mozilla {
+MaskLayerImageCache::MaskLayerImageCache()
+{
+ mMaskImageContainers.Init();
+}
+MaskLayerImageCache::~MaskLayerImageCache()
+{}
+
+
/* static */ PLDHashOperator
MaskLayerImageCache::SweepFunc(MaskLayerImageEntry* aEntry,
void* aUserArg)
{
const MaskLayerImageCache::MaskLayerImageKey* key = aEntry->mKey;
if (key->mLayerCount == 0) {
return PL_DHASH_REMOVE;
--- a/layout/base/MaskLayerImageCache.h
+++ b/layout/base/MaskLayerImageCache.h
@@ -3,20 +3,23 @@
* 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 MASKLAYERIMAGECACHE_H_
#define MASKLAYERIMAGECACHE_H_
#include "FrameLayerBuilder.h"
#include "nsPresContext.h"
-#include "ImageLayers.h"
namespace mozilla {
+namespace layers {
+class ImageContainer;
+}
+
/**
* Keeps a record of image containers for mask layers, containers are mapped
* from the rounded rects used to create them.
* The cache stores MaskLayerImageEntries indexed by MaskLayerImageKeys.
* Each MaskLayerImageEntry owns a heap-allocated MaskLayerImageKey
* (heap-allocated so that a mask layer's userdata can keep a pointer to the
* key for its image, in spite of the hashtable moving its entries around).
* The key consists of the rounded rects used to create the mask,
@@ -24,20 +27,18 @@ namespace mozilla {
* of the number of layers currently using this ImageContainer.
* When the key's layer count is zero, the cache
* may remove the entry, which deletes the key object.
*/
class MaskLayerImageCache
{
typedef mozilla::layers::ImageContainer ImageContainer;
public:
- MaskLayerImageCache()
- {
- mMaskImageContainers.Init();
- }
+ MaskLayerImageCache();
+ ~MaskLayerImageCache();
/**
* Representation of a rounded rectangle in device pixel coordinates, in
* contrast to FrameLayerBuilder::Clip::RoundedRect, which uses app units.
* In particular, our internal representation uses a gfxRect, rather than
* an nsRect, so this class is easier to use with transforms.
*/
struct PixelRoundedRect
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -41,16 +41,17 @@
#include "nsCSSProps.h"
#include "nsContentUtils.h"
#include "nsSVGEffects.h"
#include "nsSVGIntegrationUtils.h"
#include "gfxDrawable.h"
#include "sampler.h"
#include "nsCSSRenderingBorders.h"
#include "mozilla/css/ImageLoader.h"
+#include "ImageContainer.h"
using namespace mozilla;
using namespace mozilla::css;
// To avoid storing this data on nsInlineFrame (bloat) and to avoid
// recalculating this for each frame in a continuation (perf), hold
// a cache of various coordinate information that we need in order
// to paint inline backgrounds.
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -36,16 +36,18 @@
#include "nsViewportFrame.h"
#include "nsSVGEffects.h"
#include "nsSVGElement.h"
#include "nsSVGClipPathFrame.h"
#include "sampler.h"
#include "nsAnimationManager.h"
#include "nsTransitionManager.h"
#include "nsIViewManager.h"
+#include "ImageLayers.h"
+#include "ImageContainer.h"
#include "mozilla/StandardInteger.h"
using namespace mozilla;
using namespace mozilla::layers;
typedef FrameMetrics::ViewID ViewID;
static void AddTransformFunctions(nsCSSValueList* aList,
@@ -1378,16 +1380,23 @@ nsDisplayBackground::nsDisplayBackground
nsStyleContext* bgSC;
bool hasBG = nsCSSRendering::FindBackground(presContext, mFrame, &bgSC);
if (hasBG && bgSC->GetStyleBackground()->HasFixedBackground()) {
aBuilder->SetHasFixedItems();
}
}
}
+nsDisplayBackground::~nsDisplayBackground()
+{
+#ifdef NS_BUILD_REFCNT_LOGGING
+ MOZ_COUNT_DTOR(nsDisplayBackground);
+#endif
+}
+
// Helper for RoundedRectIntersectsRect.
static bool
CheckCorner(nscoord aXOffset, nscoord aYOffset,
nscoord aXRadius, nscoord aYRadius)
{
NS_ABORT_IF_FALSE(aXOffset > 0 && aYOffset > 0,
"must not pass nonpositives to CheckCorner");
NS_ABORT_IF_FALSE(aXRadius >= 0 && aYRadius >= 0,
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -18,30 +18,36 @@
#include "nsPoint.h"
#include "nsRect.h"
#include "nsISelection.h"
#include "nsCaret.h"
#include "plarena.h"
#include "nsRegion.h"
#include "FrameLayerBuilder.h"
#include "nsThemeConstants.h"
-#include "ImageLayers.h"
#include "nsLayoutUtils.h"
#include "mozilla/StandardInteger.h"
#include <stdlib.h>
class nsIPresShell;
class nsIContent;
class nsRenderingContext;
class nsDeviceContext;
class nsDisplayTableItem;
class nsDisplayItem;
+namespace mozilla {
+namespace layers {
+class ImageLayer;
+class ImageContainer;
+} //namepsace
+} //namepsace
+
/*
* An nsIFrame can have many different visual parts. For example an image frame
* can have a background, border, and outline, the image itself, and a
* translucent selection overlay. In general these parts can be drawn at
* discontiguous z-levels; see CSS2.1 appendix E:
* http://www.w3.org/TR/CSS21/zindex.html
*
* We construct a display list for a frame tree that contains one item
@@ -1587,21 +1593,17 @@ private:
};
/**
* The standard display item to paint the CSS background of a frame.
*/
class nsDisplayBackground : public nsDisplayItem {
public:
nsDisplayBackground(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);
-#ifdef NS_BUILD_REFCNT_LOGGING
- virtual ~nsDisplayBackground() {
- MOZ_COUNT_DTOR(nsDisplayBackground);
- }
-#endif
+ virtual ~nsDisplayBackground();
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerParameters& aParameters);
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerParameters& aContainerParameters);
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -61,16 +61,17 @@
#include "nsContentPolicyUtils.h"
#include "nsEventStates.h"
#include "nsError.h"
#include "nsBidiUtils.h"
#include "nsBidiPresUtils.h"
#include "gfxRect.h"
#include "ImageLayers.h"
+#include "ImageContainer.h"
#include "mozilla/Preferences.h"
#include "mozilla/Util.h" // for DebugOnly
using namespace mozilla;
// sizes (pixels) for image icon, padding and border frame
#define ICON_SIZE (16)
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -83,16 +83,17 @@
#include "nsPluginNativeWindow.h"
#include "nsIPluginDocument.h"
#include "FrameLayerBuilder.h"
#include "nsThreadUtils.h"
#include "gfxContext.h"
#include "gfxPlatform.h"
+#include "ImageLayers.h"
#ifdef XP_WIN
#include "gfxWindowsNativeDrawing.h"
#include "gfxWindowsSurface.h"
#endif
#include "gfxImageSurface.h"
#include "gfxUtils.h"
--- a/layout/generic/nsVideoFrame.cpp
+++ b/layout/generic/nsVideoFrame.cpp
@@ -23,16 +23,18 @@
#include "nsContentCreatorFunctions.h"
#include "nsBoxLayoutState.h"
#include "nsBoxFrame.h"
#include "nsImageFrame.h"
#include "nsIImageLoadingContent.h"
#include "nsCSSRendering.h"
#include "nsContentUtils.h"
#include "mozilla/layers/ShadowLayers.h"
+#include "ImageContainer.h"
+#include "ImageLayers.h"
#ifdef ACCESSIBILITY
#include "nsAccessibilityService.h"
#endif
using namespace mozilla;
using namespace mozilla::layers;
using namespace mozilla::dom;
--- a/widget/gonk/Framebuffer.cpp
+++ b/widget/gonk/Framebuffer.cpp
@@ -30,16 +30,17 @@
#include "android/log.h"
#include "Framebuffer.h"
#include "gfxContext.h"
#include "gfxImageSurface.h"
#include "gfxUtils.h"
#include "mozilla/FileUtils.h"
#include "nsTArray.h"
+#include "nsRegion.h"
#define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
using namespace std;
namespace mozilla {
namespace Framebuffer {
--- a/widget/gonk/nsWindow.cpp
+++ b/widget/gonk/nsWindow.cpp
@@ -20,16 +20,17 @@
#include "android/log.h"
#include "ui/FramebufferNativeWindow.h"
#include "mozilla/Hal.h"
#include "mozilla/Preferences.h"
#include "mozilla/FileUtils.h"
#include "Framebuffer.h"
#include "gfxContext.h"
+#include "gfxPlatform.h"
#include "gfxUtils.h"
#include "GLContextProvider.h"
#include "LayerManagerOGL.h"
#include "nsAutoPtr.h"
#include "nsAppShell.h"
#include "nsIdleService.h"
#include "nsScreenManagerGonk.h"
#include "nsTArray.h"