Merge mozilla-central and inbound

This commit is contained in:
Ed Morley 2013-07-09 08:55:20 +01:00
commit ef82d94fe6
64 changed files with 3046 additions and 2501 deletions

View File

@ -304,7 +304,7 @@ public:
/*
* This is the base class for source surfaces. These objects are surfaces
* which may be used as a source in a SurfacePattern of a DrawSurface call.
* which may be used as a source in a SurfacePattern or a DrawSurface call.
* They cannot be drawn to directly.
*/
class SourceSurface : public RefCounted<SourceSurface>

View File

@ -2026,13 +2026,137 @@ GLContext::BlitTextureImage(TextureImage *aSrc, const nsIntRect& aSrcRect,
}
static unsigned int
DataOffset(gfxImageSurface *aSurf, const nsIntPoint &aPoint)
DataOffset(const nsIntPoint &aPoint, int32_t aStride, gfxASurface::gfxImageFormat aFormat)
{
unsigned int data = aPoint.y * aSurf->Stride();
data += aPoint.x * gfxASurface::BytePerPixelFromFormat(aSurf->Format());
unsigned int data = aPoint.y * aStride;
data += aPoint.x * gfxASurface::BytePerPixelFromFormat(aFormat);
return data;
}
GLContext::SurfaceFormat
GLContext::UploadImageDataToTexture(unsigned char* aData,
int32_t aStride,
gfxASurface::gfxImageFormat aFormat,
const nsIntRegion& aDstRegion,
GLuint& aTexture,
bool aOverwrite,
bool aPixelBuffer,
GLenum aTextureUnit,
GLenum aTextureTarget)
{
bool textureInited = aOverwrite ? false : true;
MakeCurrent();
fActiveTexture(aTextureUnit);
if (!aTexture) {
fGenTextures(1, &aTexture);
fBindTexture(aTextureTarget, aTexture);
fTexParameteri(aTextureTarget,
LOCAL_GL_TEXTURE_MIN_FILTER,
LOCAL_GL_LINEAR);
fTexParameteri(aTextureTarget,
LOCAL_GL_TEXTURE_MAG_FILTER,
LOCAL_GL_LINEAR);
fTexParameteri(aTextureTarget,
LOCAL_GL_TEXTURE_WRAP_S,
LOCAL_GL_CLAMP_TO_EDGE);
fTexParameteri(aTextureTarget,
LOCAL_GL_TEXTURE_WRAP_T,
LOCAL_GL_CLAMP_TO_EDGE);
textureInited = false;
} else {
fBindTexture(aTextureTarget, aTexture);
}
nsIntRegion paintRegion;
if (!textureInited) {
paintRegion = nsIntRegion(aDstRegion.GetBounds());
} else {
paintRegion = aDstRegion;
}
GLenum format;
GLenum type;
int32_t pixelSize = gfxASurface::BytePerPixelFromFormat(aFormat);
SurfaceFormat surfaceFormat;
switch (aFormat) {
case gfxASurface::ImageFormatARGB32:
format = LOCAL_GL_RGBA;
type = LOCAL_GL_UNSIGNED_BYTE;
surfaceFormat = FORMAT_B8G8R8A8;
break;
case gfxASurface::ImageFormatRGB24:
// Treat RGB24 surfaces as RGBA32 except for the shader
// program used.
format = LOCAL_GL_RGBA;
type = LOCAL_GL_UNSIGNED_BYTE;
surfaceFormat = FORMAT_B8G8R8X8;
break;
case gfxASurface::ImageFormatRGB16_565:
format = LOCAL_GL_RGB;
type = LOCAL_GL_UNSIGNED_SHORT_5_6_5;
surfaceFormat = FORMAT_R5G6B5;
break;
case gfxASurface::ImageFormatA8:
format = LOCAL_GL_LUMINANCE;
type = LOCAL_GL_UNSIGNED_BYTE;
// We don't have a specific luminance shader
surfaceFormat = FORMAT_A8;
break;
default:
NS_ASSERTION(false, "Unhandled image surface format!");
format = 0;
type = 0;
surfaceFormat = FORMAT_UNKNOWN;
}
nsIntRegionRectIterator iter(paintRegion);
const nsIntRect *iterRect;
// Top left point of the region's bounding rectangle.
nsIntPoint topLeft = paintRegion.GetBounds().TopLeft();
while ((iterRect = iter.Next())) {
// The inital data pointer is at the top left point of the region's
// bounding rectangle. We need to find the offset of this rect
// within the region and adjust the data pointer accordingly.
unsigned char *rectData =
aData + DataOffset(iterRect->TopLeft() - topLeft, aStride, aFormat);
NS_ASSERTION(textureInited || (iterRect->x == 0 && iterRect->y == 0),
"Must be uploading to the origin when we don't have an existing texture");
if (textureInited && CanUploadSubTextures()) {
TexSubImage2D(aTextureTarget,
0,
iterRect->x,
iterRect->y,
iterRect->width,
iterRect->height,
aStride,
pixelSize,
format,
type,
rectData);
} else {
TexImage2D(aTextureTarget,
0,
format,
iterRect->width,
iterRect->height,
aStride,
pixelSize,
0,
format,
type,
rectData);
}
}
return surfaceFormat;
}
GLContext::SurfaceFormat
GLContext::UploadSurfaceToTexture(gfxASurface *aSurface,
const nsIntRegion& aDstRegion,
@ -2040,38 +2164,9 @@ GLContext::UploadSurfaceToTexture(gfxASurface *aSurface,
bool aOverwrite,
const nsIntPoint& aSrcPoint,
bool aPixelBuffer,
GLenum aTextureUnit)
GLenum aTextureUnit,
GLenum aTextureTarget)
{
bool textureInited = aOverwrite ? false : true;
MakeCurrent();
fActiveTexture(aTextureUnit);
if (!aTexture) {
fGenTextures(1, &aTexture);
fBindTexture(LOCAL_GL_TEXTURE_2D, aTexture);
fTexParameteri(LOCAL_GL_TEXTURE_2D,
LOCAL_GL_TEXTURE_MIN_FILTER,
LOCAL_GL_LINEAR);
fTexParameteri(LOCAL_GL_TEXTURE_2D,
LOCAL_GL_TEXTURE_MAG_FILTER,
LOCAL_GL_LINEAR);
fTexParameteri(LOCAL_GL_TEXTURE_2D,
LOCAL_GL_TEXTURE_WRAP_S,
LOCAL_GL_CLAMP_TO_EDGE);
fTexParameteri(LOCAL_GL_TEXTURE_2D,
LOCAL_GL_TEXTURE_WRAP_T,
LOCAL_GL_CLAMP_TO_EDGE);
textureInited = false;
} else {
fBindTexture(LOCAL_GL_TEXTURE_2D, aTexture);
}
nsIntRegion paintRegion;
if (!textureInited) {
paintRegion = nsIntRegion(aDstRegion.GetBounds());
} else {
paintRegion = aDstRegion;
}
nsRefPtr<gfxImageSurface> imageSurface = aSurface->GetAsImageSurface();
unsigned char* data = NULL;
@ -2101,94 +2196,56 @@ GLContext::UploadSurfaceToTexture(gfxASurface *aSurface,
if (!aPixelBuffer) {
data = imageSurface->Data();
}
data += DataOffset(imageSurface, aSrcPoint);
data += DataOffset(aSrcPoint, imageSurface->Stride(),
imageSurface->Format());
}
MOZ_ASSERT(imageSurface);
imageSurface->Flush();
GLenum format;
GLenum type;
int32_t pixelSize = gfxASurface::BytePerPixelFromFormat(imageSurface->Format());
SurfaceFormat surfaceFormat;
return UploadImageDataToTexture(data,
imageSurface->Stride(),
imageSurface->Format(),
aDstRegion, aTexture, aOverwrite,
aPixelBuffer, aTextureUnit, aTextureTarget);
}
switch (imageSurface->Format()) {
case gfxASurface::ImageFormatARGB32:
format = LOCAL_GL_RGBA;
type = LOCAL_GL_UNSIGNED_BYTE;
surfaceFormat = FORMAT_B8G8R8A8;
break;
case gfxASurface::ImageFormatRGB24:
// Treat RGB24 surfaces as RGBA32 except for the shader
// program used.
format = LOCAL_GL_RGBA;
type = LOCAL_GL_UNSIGNED_BYTE;
surfaceFormat = FORMAT_B8G8R8X8;
break;
case gfxASurface::ImageFormatRGB16_565:
format = LOCAL_GL_RGB;
type = LOCAL_GL_UNSIGNED_SHORT_5_6_5;
surfaceFormat = FORMAT_R5G6B5;
break;
case gfxASurface::ImageFormatA8:
format = LOCAL_GL_LUMINANCE;
type = LOCAL_GL_UNSIGNED_BYTE;
surfaceFormat = FORMAT_A8;
break;
static gfxASurface::gfxImageFormat
ImageFormatForSurfaceFormat(gfx::SurfaceFormat aFormat)
{
switch (aFormat) {
case gfx::FORMAT_B8G8R8A8:
return gfxASurface::ImageFormatARGB32;
case gfx::FORMAT_B8G8R8X8:
return gfxASurface::ImageFormatRGB24;
case gfx::FORMAT_R5G6B5:
return gfxASurface::ImageFormatRGB16_565;
case gfx::FORMAT_A8:
return gfxASurface::ImageFormatA8;
default:
NS_ASSERTION(false, "Unhandled image surface format!");
format = 0;
type = 0;
surfaceFormat = FORMAT_UNKNOWN;
return gfxASurface::ImageFormatUnknown;
}
}
int32_t stride = imageSurface->Stride();
nsIntRegionRectIterator iter(paintRegion);
const nsIntRect *iterRect;
// Top left point of the region's bounding rectangle.
nsIntPoint topLeft = paintRegion.GetBounds().TopLeft();
while ((iterRect = iter.Next())) {
// The inital data pointer is at the top left point of the region's
// bounding rectangle. We need to find the offset of this rect
// within the region and adjust the data pointer accordingly.
unsigned char *rectData =
data + DataOffset(imageSurface, iterRect->TopLeft() - topLeft);
NS_ASSERTION(textureInited || (iterRect->x == 0 && iterRect->y == 0),
"Must be uploading to the origin when we don't have an existing texture");
if (textureInited && CanUploadSubTextures()) {
TexSubImage2D(LOCAL_GL_TEXTURE_2D,
0,
iterRect->x,
iterRect->y,
iterRect->width,
iterRect->height,
stride,
pixelSize,
format,
type,
rectData);
} else {
TexImage2D(LOCAL_GL_TEXTURE_2D,
0,
format,
iterRect->width,
iterRect->height,
stride,
pixelSize,
0,
format,
type,
rectData);
}
}
return surfaceFormat;
GLContext::SurfaceFormat
GLContext::UploadSurfaceToTexture(gfx::DataSourceSurface *aSurface,
const nsIntRegion& aDstRegion,
GLuint& aTexture,
bool aOverwrite,
const nsIntPoint& aSrcPoint,
bool aPixelBuffer,
GLenum aTextureUnit,
GLenum aTextureTarget)
{
unsigned char* data = aPixelBuffer ? NULL : aSurface->GetData();
int32_t stride = aSurface->Stride();
gfxASurface::gfxImageFormat format =
ImageFormatForSurfaceFormat(aSurface->GetFormat());
data += DataOffset(aSrcPoint, stride, format);
return UploadImageDataToTexture(data, stride, format,
aDstRegion, aTexture, aOverwrite,
aPixelBuffer, aTextureUnit,
aTextureTarget);
}
static GLint GetAddressAlignment(ptrdiff_t aAddress)

View File

@ -62,6 +62,7 @@ namespace android {
namespace mozilla {
namespace gfx {
class SharedSurface;
class DataSourceSurface;
struct SurfaceCaps;
}
@ -866,7 +867,7 @@ public:
* The aDstPoint parameter is ignored if no texture was provided
* or aOverwrite is true.
*
* \param aSurface Surface to upload.
* \param aData Image data to upload.
* \param aDstRegion Region of texture to upload to.
* \param aTexture Texture to use, or 0 to have one created for you.
* \param aOverwrite Over an existing texture with a new one.
@ -881,14 +882,39 @@ public:
* texture unit being active.
* \return Surface format of this texture.
*/
SurfaceFormat UploadImageDataToTexture(unsigned char* aData,
int32_t aStride,
gfxASurface::gfxImageFormat aFormat,
const nsIntRegion& aDstRegion,
GLuint& aTexture,
bool aOverwrite = false,
bool aPixelBuffer = false,
GLenum aTextureUnit = LOCAL_GL_TEXTURE0,
GLenum aTextureTarget = LOCAL_GL_TEXTURE_2D);
/**
* Convenience wrapper around UploadImageDataToTexture for gfxASurfaces.
*/
SurfaceFormat UploadSurfaceToTexture(gfxASurface *aSurface,
const nsIntRegion& aDstRegion,
GLuint& aTexture,
bool aOverwrite = false,
const nsIntPoint& aSrcPoint = nsIntPoint(0, 0),
bool aPixelBuffer = false,
GLenum aTextureUnit = LOCAL_GL_TEXTURE0);
GLenum aTextureUnit = LOCAL_GL_TEXTURE0,
GLenum aTextureTarget = LOCAL_GL_TEXTURE_2D);
/**
* Same as above, for DataSourceSurfaces.
*/
SurfaceFormat UploadSurfaceToTexture(gfx::DataSourceSurface *aSurface,
const nsIntRegion& aDstRegion,
GLuint& aTexture,
bool aOverwrite = false,
const nsIntPoint& aSrcPoint = nsIntPoint(0, 0),
bool aPixelBuffer = false,
GLenum aTextureUnit = LOCAL_GL_TEXTURE0,
GLenum aTextureTarget = LOCAL_GL_TEXTURE_2D);
void TexImage2D(GLenum target, GLint level, GLint internalformat,
GLsizei width, GLsizei height, GLsizei stride,

View File

@ -214,7 +214,7 @@ public:
* Clients of the compositor should call this at the start of the compositing
* process, it might be required by texture uploads etc.
*
* If aFlags == CURRENT_FORCE then we will (re-)set our context on the
* If aFlags == ForceMakeCurrent then we will (re-)set our context on the
* underlying API even if it is already the current context.
*/
virtual void MakeCurrent(MakeCurrentFlags aFlags = 0) = 0;

View File

@ -187,10 +187,15 @@ BasicCompositor::BasicCompositor(nsIWidget *aWidget)
BasicCompositor::~BasicCompositor()
{
Destroy();
MOZ_COUNT_DTOR(BasicCompositor);
}
void BasicCompositor::Destroy()
{
mWidget->CleanupRemoteDrawing();
mWidget = nullptr;
}
TemporaryRef<CompositingRenderTarget>
BasicCompositor::CreateRenderTarget(const IntRect& aRect, SurfaceInitMode aInit)
{
@ -357,6 +362,8 @@ BasicCompositor::BeginFrame(const gfx::Rect *aClipRectIn,
// If we have a copy target, then we don't have a widget-provided mDrawTarget (currently). Create a dummy
// placeholder so that CreateRenderTarget() works.
mDrawTarget = gfxPlatform::GetPlatform()->CreateOffscreenDrawTarget(IntSize(1,1), FORMAT_B8G8R8A8);
} else {
mDrawTarget = mWidget->StartRemoteDrawing();
}
if (!mDrawTarget) {
if (aRenderBoundsOut) {
@ -395,13 +402,28 @@ BasicCompositor::EndFrame()
mCopyTarget->SetOperator(gfxContext::OPERATOR_SOURCE);
mCopyTarget->SetSource(thebes);
mCopyTarget->Paint();
mCopyTarget = nullptr;
} else {
// Most platforms require us to buffer drawing to the widget surface.
// That's why we don't draw to mDrawTarget directly.
RefPtr<SourceSurface> source = mRenderTarget->mDrawTarget->Snapshot();
mDrawTarget->DrawSurface(source,
Rect(0, 0, mWidgetSize.width, mWidgetSize.height),
Rect(0, 0, mWidgetSize.width, mWidgetSize.height),
DrawSurfaceOptions(),
DrawOptions());
mWidget->EndRemoteDrawing();
}
mDrawTarget = nullptr;
mRenderTarget = nullptr;
}
void
BasicCompositor::AbortFrame()
{
mDrawTarget->PopClip();
mRenderTarget->mDrawTarget->PopClip();
mDrawTarget = nullptr;
mRenderTarget = nullptr;
}
}

View File

@ -34,7 +34,7 @@ public:
virtual bool Initialize() MOZ_OVERRIDE { return true; };
virtual void Destroy() MOZ_OVERRIDE { };
virtual void Destroy() MOZ_OVERRIDE;
virtual TextureFactoryIdentifier GetTextureFactoryIdentifier() MOZ_OVERRIDE
{

View File

@ -55,7 +55,7 @@ public:
virtual void FlushRendering() MOZ_OVERRIDE;
virtual bool NeedsWidgetInvalidation() MOZ_OVERRIDE { return Compositor::GetBackend() == LAYERS_BASIC; }
virtual bool NeedsWidgetInvalidation() MOZ_OVERRIDE { return false; }
ShadowableLayer* Hold(Layer* aLayer);

View File

@ -24,7 +24,7 @@ class SurfaceDescriptor;
/**
* CompositableClient manages the texture-specific logic for composite layers,
* independently of the layer. It is the content side of a ConmpositableClient/
* independently of the layer. It is the content side of a CompositableClient/
* CompositableHost pair.
*
* CompositableClient's purpose is to send texture data to the compositor side

View File

@ -53,7 +53,7 @@ class BasicLayerManager;
* Updated() is called when we are done painting and packages up the change in
* the appropriate way to be passed to the compositor in the layers transation.
*
* SwapBuffers is called in repsonse to the transaction reply from the compositor.
* SwapBuffers is called in response to the transaction reply from the compositor.
*/
class ContentClient : public CompositableClient
{
@ -155,7 +155,7 @@ private:
* the rendering side and destroyed on the compositing side. They are only
* passed from one side to the other when the TextureClient/Hosts are created.
* *Ownership* of the SurfaceDescriptor moves from the rendering side to the
* comnpositing side with the create message (send from CreateBuffer) which
* compositing side with the create message (send from CreateBuffer) which
* tells the compositor that TextureClients have been created and that the
* compositor should assign the corresponding TextureHosts to our corresponding
* ContentHost.
@ -273,8 +273,8 @@ protected:
* into mTextureClient at any time.
*
* The ContentHost keeps a reference to both corresponding texture hosts, in
* repsonse to our UpdateTextureRegion message, the compositor swaps its
* references. In repsonse to the compositor's reply we swap our references
* response to our UpdateTextureRegion message, the compositor swaps its
* references. In response to the compositor's reply we swap our references
* (in SwapBuffers).
*/
class ContentClientDoubleBuffered : public ContentClientRemoteBuffer
@ -311,7 +311,7 @@ private:
* A single buffered ContentClient. We have a single TextureClient/Host
* which we update and then send a message to the compositor that we are
* done updating. It is not safe for the compositor to use the corresponding
* TextureHost's memory directly, it most upload it to video memory of some
* TextureHost's memory directly, it must upload it to video memory of some
* kind. We are free to modify the TextureClient once we receive reply from
* the compositor.
*/

View File

@ -133,7 +133,7 @@ public:
/**
* Performs a progressive update of a given tiled buffer.
* See ComputeProgressiveUpdateRegion above for parameter documentation.
* See ComputeProgressiveUpdateRegion below for parameter documentation.
*/
bool ProgressiveUpdate(nsIntRegion& aValidRegion,
nsIntRegion& aInvalidRegion,
@ -198,10 +198,6 @@ private:
* current transaction.
* aRegionToPaint will be filled with the region to update. This may be empty,
* which indicates that there is no more work to do.
* aTransform is the transform required to convert from screen-space to
* layer-space.
* aScrollOffset is the current scroll offset of the primary scrollable layer.
* aResolution is the render resolution of the layer.
* aIsRepeated should be true if this function has already been called during
* this transaction.
*

View File

@ -77,7 +77,7 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation
compositable->SetLayer(layer);
} else {
// if we reach this branch, it most likely means that async textures
// are coming in before we had time to attach the conmpositable to a
// are coming in before we had time to attach the compositable to a
// layer. Don't panic, it is okay in this case. it should not be
// happening continuously, though.
}

View File

@ -126,6 +126,14 @@ ProgramProfileOGL::GetProfileFor(ShaderProgramType aType,
AddCommonTextureArgs(result);
result.mTextureCount = 1;
break;
case BGRARectLayerProgramType:
MOZ_ASSERT(aMask == MaskNone, "BGRARectLayerProgramType can't handle masks.");
result.mVertexShaderString = sLayerVS;
result.mFragmentShaderString = sBGRARectTextureLayerFS;
AddCommonArgs(result);
AddCommonTextureArgs(result);
result.mTextureCount = 1;
break;
case RGBAExternalLayerProgramType:
if (aMask == Mask3d) {
result.mVertexShaderString = sLayerMask3DVS;

View File

@ -37,6 +37,7 @@ enum ShaderProgramType {
RGBXLayerProgramType,
BGRXLayerProgramType,
RGBARectLayerProgramType,
BGRARectLayerProgramType,
RGBAExternalLayerProgramType,
ColorLayerProgramType,
YCbCrLayerProgramType,
@ -126,6 +127,10 @@ struct ProgramProfileOGL
aType == Copy2DRectProgramType))
return false;
if (aMask != MaskNone &&
aType == BGRARectLayerProgramType)
return false;
return aMask != Mask3d ||
aType == RGBARectLayerProgramType ||
aType == RGBALayerProgramType;

View File

@ -473,6 +473,34 @@ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n\
#endif\n\
";
static const char sBGRARectTextureLayerFS[] = "/* sBGRARectTextureLayerFS */\n\
#extension GL_ARB_texture_rectangle : enable\n\
/* Fragment Shader */\n\
#ifdef GL_ES\n\
#ifdef MEDIUMP_SHADER\n\
precision mediump float;\n\
#else\n\
precision lowp float;\n\
#endif\n\
#endif\n\
\n\
#ifndef NO_LAYER_OPACITY\n\
uniform float uLayerOpacity;\n\
#endif\n\
#ifdef GL_ES // for tiling, texcoord can be greater than the lowfp range\n\
varying mediump vec2 vTexCoord;\n\
#else\n\
varying vec2 vTexCoord;\n\
#endif\n\
\n\
uniform sampler2DRect uTexture;\n\
uniform vec2 uTexCoordMultiplier;\n\
void main()\n\
{\n\
gl_FragColor = texture2DRect(uTexture, vec2(vTexCoord * uTexCoordMultiplier)).bgra * uLayerOpacity;\n\
}\n\
";
static const char sRGBAExternalTextureLayerFS[] = "/* sRGBAExternalTextureLayerFS */\n\
#extension GL_OES_EGL_image_external : require\n\
/* Fragment Shader */\n\

View File

@ -257,6 +257,22 @@ void main()
#endif
@end
// Single texture in BGRA format, but with a Rect texture.
// nsChildView needs this for old Mac hardware.
@shader sBGRARectTextureLayerFS
#extension GL_ARB_texture_rectangle : enable
$LAYER_FRAGMENT<>$
uniform sampler2DRect uTexture;
uniform vec2 uTexCoordMultiplier;
void main()
{
gl_FragColor = texture2DRect(uTexture, vec2(vTexCoord * uTexCoordMultiplier)).bgra * uLayerOpacity;
}
@end
// Single texture in RGBA format, but uses external image. External
// image is an EGLImage which have internal formats not otherwise
// supported by OpenGL ES. It is up to the implementation exactly what

View File

@ -26,7 +26,7 @@ class CompositorOGL;
/*
* TextureHost implementations for the OpenGL backend.
*
* Note that it is important to becareful about the ownership model with
* Note that it is important to be careful about the ownership model with
* the OpenGL backend, due to some widget limitation on Linux: before
* the nsBaseWidget associated with our OpenGL context has been completely
* deleted, every resource belonging to the OpenGL context MUST have been

View File

@ -577,6 +577,12 @@ gfxUtils::ClipToRegion(gfxContext* aContext, const nsIntRegion& aRegion)
ClipToRegionInternal(aContext, aRegion, false);
}
/*static*/ void
gfxUtils::ClipToRegion(DrawTarget* aTarget, const nsIntRegion& aRegion)
{
ClipToRegionInternal(aTarget, aRegion, false);
}
/*static*/ void
gfxUtils::ClipToRegionSnapped(gfxContext* aContext, const nsIntRegion& aRegion)
{

View File

@ -66,13 +66,18 @@ public:
*/
static void ClipToRegion(gfxContext* aContext, const nsIntRegion& aRegion);
/**
* Clip aTarget to the region aRegion.
*/
static void ClipToRegion(mozilla::gfx::DrawTarget* aTarget, const nsIntRegion& aRegion);
/**
* Clip aContext to the region aRegion, snapping the rectangles.
*/
static void ClipToRegionSnapped(gfxContext* aContext, const nsIntRegion& aRegion);
/**
* Clip aContext to the region aRegion, snapping the rectangles.
* Clip aTarget to the region aRegion, snapping the rectangles.
*/
static void ClipToRegionSnapped(mozilla::gfx::DrawTarget* aTarget, const nsIntRegion& aRegion);

View File

@ -334,10 +334,7 @@ check-jstests:
#
# Bug 652155: On Mac, SM(d) doesn't work for unknown reasons
ifeq ($(OS_ARCH),WINNT)
ifdef ENABLE_METHODJIT
endif
else
ifneq ($(OS_ARCH),WINNT)
ifndef HAVE_DTRACE
#check:: check-jstests
endif

View File

@ -8,9 +8,10 @@
#define builtin_MapObject_h
#include "jsapi.h"
#include "jscntxt.h"
#include "jsobj.h"
#include "vm/Runtime.h"
namespace js {
/*

View File

@ -2067,41 +2067,25 @@ dnl Configure JIT support
case "$target" in
i?86-*)
ENABLE_METHODJIT=1
ENABLE_ION=1
ENABLE_MONOIC=1
ENABLE_POLYIC=1
ENABLE_METHODJIT_TYPED_ARRAY=1
ENABLE_YARR_JIT=1
AC_DEFINE(JS_CPU_X86)
AC_DEFINE(JS_NUNBOX32)
;;
x86_64*-*)
ENABLE_METHODJIT=1
ENABLE_ION=1
ENABLE_MONOIC=1
ENABLE_POLYIC=1
ENABLE_METHODJIT_TYPED_ARRAY=1
ENABLE_YARR_JIT=1
AC_DEFINE(JS_CPU_X64)
AC_DEFINE(JS_PUNBOX64)
;;
arm*-*)
ENABLE_METHODJIT=1
ENABLE_ION=1
ENABLE_MONOIC=1
ENABLE_POLYIC=1
ENABLE_METHODJIT_TYPED_ARRAY=1
ENABLE_YARR_JIT=1
AC_DEFINE(JS_CPU_ARM)
AC_DEFINE(JS_NUNBOX32)
;;
sparc*-*)
if test ! "$HAVE_64BIT_OS" ; then
ENABLE_METHODJIT=1
ENABLE_MONOIC=1
ENABLE_POLYIC=1
ENABLE_METHODJIT_TYPED_ARRAY=1
ENABLE_YARR_JIT=1
dnl ENABLE_ION=0
AC_DEFINE(JS_CPU_SPARC)
@ -2109,10 +2093,6 @@ dnl ENABLE_ION=0
fi
;;
mips*-*)
ENABLE_METHODJIT=1
ENABLE_MONOIC=1
ENABLE_POLYIC=1
ENABLE_METHODJIT_TYPED_ARRAY=1
ENABLE_YARR_JIT=1
AC_DEFINE(JS_CPU_MIPS)
AC_DEFINE(JS_NUNBOX32)
@ -2127,27 +2107,8 @@ MOZ_ARG_DISABLE_BOOL(yarr-jit,
[ --disable-yarr-jit Disable YARR JIT support],
ENABLE_YARR_JIT= )
AC_SUBST(ENABLE_METHODJIT)
AC_SUBST(ENABLE_METHODJIT_SPEW)
if test "$ENABLE_METHODJIT"; then
AC_DEFINE(JS_METHODJIT)
else
ENABLE_ION=
fi
if test "$ENABLE_MONOIC"; then
AC_DEFINE(JS_MONOIC)
fi
if test "$ENABLE_POLYIC"; then
AC_DEFINE(JS_POLYIC)
fi
if test "$ENABLE_METHODJIT_TYPED_ARRAY"; then
AC_DEFINE(JS_METHODJIT_TYPED_ARRAY)
fi
AC_SUBST(ENABLE_ION)
if test "$ENABLE_ION"; then
@ -3278,7 +3239,7 @@ MOZ_ARG_ENABLE_STRING(debug,
(using compiler flags DBG)],
[ if test "$enableval" != "no"; then
MOZ_DEBUG=1
if test "$ENABLE_METHODJIT" -o "$ENABLE_YARR_JIT"; then
if test "$ENABLE_YARR_JIT"; then
# needs MethodJIT or YarrJIT
ENABLE_METHODJIT_SPEW=1
fi

View File

@ -9,6 +9,8 @@
#include "jsapi.h"
#include "vm/Runtime.h"
namespace js {
namespace gc {

View File

@ -5,11 +5,11 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "jsapi.h"
#include "jscntxt.h"
#include "jsgc.h"
#include "js/HashTable.h"
#include "gc/GCInternals.h"
#include "vm/Runtime.h"
#include "jsgcinlines.h"

View File

@ -8,7 +8,6 @@
#define gc_Marking_h
#include "jsgc.h"
#include "jscntxt.h"
#include "jslock.h"
#include "gc/Barrier.h"

View File

@ -6,9 +6,8 @@
#include "gc/Memory.h"
#include "jscntxt.h"
#include "js/HeapAPI.h"
#include "vm/Runtime.h"
using namespace js;
using namespace js::gc;

View File

@ -11,12 +11,12 @@
#include "mozilla/PodOperations.h"
#include "jscntxt.h"
#include "jscrashreport.h"
#include "jsprf.h"
#include "jsutil.h"
#include "prmjtime.h"
#include "gc/Memory.h"
#include "vm/Runtime.h"
using namespace js;
using namespace js::gcstats;

View File

@ -4,16 +4,15 @@
* 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 "jscntxt.h"
#include "jsgc.h"
#include "vm/Debugger.h"
#ifdef JS_ION
#include "ion/BaselineJIT.h"
#include "ion/IonCompartment.h"
#include "ion/Ion.h"
#endif
#include "vm/Debugger.h"
#include "vm/Runtime.h"
#include "jsgcinlines.h"

View File

@ -19,7 +19,7 @@
#include "ion/FixedArityList.h"
// ARM defines the RegisterID within Architecture-arm.h
#if !defined(JS_CPU_ARM) && defined(JS_METHODJIT)
#if !defined(JS_CPU_ARM)
#include "assembler/assembler/MacroAssembler.h"
#endif

View File

@ -38,10 +38,6 @@
JS_HAVE_STDINT_H. */
#undef JS_BYTES_PER_WORD
/* Some mozilla code uses JS-friend APIs that depend on JS_METHODJIT being
correct. */
#undef JS_METHODJIT
/* MOZILLA JSAPI version number components */
#undef MOZJS_MAJOR_VERSION
#undef MOZJS_MINOR_VERSION

View File

@ -12,10 +12,11 @@
#include "mozilla/PodOperations.h"
#include "jscompartment.h"
#include "jscntxt.h"
#include "jsinfer.h"
#include "jsscript.h"
#include "vm/Runtime.h"
class JSScript;
namespace js {

View File

@ -37,6 +37,7 @@
#include "vm/ArgumentsObject-inl.h"
#include "vm/Interpreter-inl.h"
#include "vm/ObjectImpl-inl.h"
#include "vm/Runtime-inl.h"
using namespace js;
using namespace js::gc;

View File

@ -99,128 +99,6 @@ js::TraceCycleDetectionSet(JSTracer *trc, js::ObjectSet &set)
}
}
void
NewObjectCache::clearNurseryObjects(JSRuntime *rt)
{
for (unsigned i = 0; i < mozilla::ArrayLength(entries); ++i) {
Entry &e = entries[i];
JSObject *obj = reinterpret_cast<JSObject *>(&e.templateObject);
if (IsInsideNursery(rt, e.key) ||
IsInsideNursery(rt, obj->slots) ||
IsInsideNursery(rt, obj->elements))
{
mozilla::PodZero(&e);
}
}
}
void
JSRuntime::sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::RuntimeSizes *rtSizes)
{
rtSizes->object = mallocSizeOf(this);
rtSizes->atomsTable = atoms.sizeOfExcludingThis(mallocSizeOf);
rtSizes->contexts = 0;
for (ContextIter acx(this); !acx.done(); acx.next())
rtSizes->contexts += acx->sizeOfIncludingThis(mallocSizeOf);
rtSizes->dtoa = mallocSizeOf(mainThread.dtoaState);
rtSizes->temporary = tempLifoAlloc.sizeOfExcludingThis(mallocSizeOf);
rtSizes->code = JS::CodeSizes();
if (execAlloc_)
execAlloc_->sizeOfCode(&rtSizes->code);
rtSizes->regexpData = bumpAlloc_ ? bumpAlloc_->sizeOfNonHeapData() : 0;
rtSizes->interpreterStack = interpreterStack_.sizeOfExcludingThis(mallocSizeOf);
rtSizes->gcMarker = gcMarker.sizeOfExcludingThis(mallocSizeOf);
rtSizes->mathCache = mathCache_ ? mathCache_->sizeOfIncludingThis(mallocSizeOf) : 0;
rtSizes->scriptData = scriptDataTable.sizeOfExcludingThis(mallocSizeOf);
for (ScriptDataTable::Range r = scriptDataTable.all(); !r.empty(); r.popFront())
rtSizes->scriptData += mallocSizeOf(r.front());
}
void
JSRuntime::triggerOperationCallback()
{
AutoLockForOperationCallback lock(this);
/*
* Invalidate ionTop to trigger its over-recursion check. Note this must be
* set before interrupt, to avoid racing with js_InvokeOperationCallback,
* into a weird state where interrupt is stuck at 0 but ionStackLimit is
* MAXADDR.
*/
mainThread.setIonStackLimit(-1);
/*
* Use JS_ATOMIC_SET in the hope that it ensures the write will become
* immediately visible to other processors polling the flag.
*/
JS_ATOMIC_SET(&interrupt, 1);
#ifdef JS_ION
/* asm.js code uses a separate mechanism to halt running code. */
TriggerOperationCallbackForAsmJSCode(this);
#endif
}
void
JSRuntime::setJitHardening(bool enabled)
{
jitHardening = enabled;
if (execAlloc_)
execAlloc_->setRandomize(enabled);
}
JSC::ExecutableAllocator *
JSRuntime::createExecutableAllocator(JSContext *cx)
{
JS_ASSERT(!execAlloc_);
JS_ASSERT(cx->runtime() == this);
JSC::AllocationBehavior randomize =
jitHardening ? JSC::AllocationCanRandomize : JSC::AllocationDeterministic;
execAlloc_ = js_new<JSC::ExecutableAllocator>(randomize);
if (!execAlloc_)
js_ReportOutOfMemory(cx);
return execAlloc_;
}
WTF::BumpPointerAllocator *
JSRuntime::createBumpPointerAllocator(JSContext *cx)
{
JS_ASSERT(!bumpAlloc_);
JS_ASSERT(cx->runtime() == this);
bumpAlloc_ = js_new<WTF::BumpPointerAllocator>();
if (!bumpAlloc_)
js_ReportOutOfMemory(cx);
return bumpAlloc_;
}
MathCache *
JSRuntime::createMathCache(JSContext *cx)
{
JS_ASSERT(!mathCache_);
JS_ASSERT(cx->runtime() == this);
MathCache *newMathCache = js_new<MathCache>();
if (!newMathCache) {
js_ReportOutOfMemory(cx);
return NULL;
}
mathCache_ = newMathCache;
return mathCache_;
}
void
JSCompartment::sweepCallsiteClones()
{
@ -1221,50 +1099,6 @@ JSContext::~JSContext()
JS_ASSERT(!resolvingList);
}
bool
JSRuntime::setDefaultLocale(const char *locale)
{
if (!locale)
return false;
resetDefaultLocale();
defaultLocale = JS_strdup(this, locale);
return defaultLocale != NULL;
}
void
JSRuntime::resetDefaultLocale()
{
js_free(defaultLocale);
defaultLocale = NULL;
}
const char *
JSRuntime::getDefaultLocale()
{
if (defaultLocale)
return defaultLocale;
char *locale, *lang, *p;
#ifdef HAVE_SETLOCALE
locale = setlocale(LC_ALL, NULL);
#else
locale = getenv("LANG");
#endif
// convert to a well-formed BCP 47 language tag
if (!locale || !strcmp(locale, "C"))
locale = const_cast<char*>("und");
lang = JS_strdup(this, locale);
if (!lang)
return NULL;
if ((p = strchr(lang, '.')))
*p = '\0';
while ((p = strchr(lang, '_')))
*p = '-';
defaultLocale = lang;
return defaultLocale;
}
/*
* Since this function is only called in the context of a pending exception,
* the caller must subsequently take an error path. If wrapping fails, it will
@ -1351,74 +1185,6 @@ JSContext::currentlyRunning() const
return false;
}
void
JSRuntime::setGCMaxMallocBytes(size_t value)
{
/*
* For compatibility treat any value that exceeds PTRDIFF_T_MAX to
* mean that value.
*/
gcMaxMallocBytes = (ptrdiff_t(value) >= 0) ? value : size_t(-1) >> 1;
for (ZonesIter zone(this); !zone.done(); zone.next())
zone->setGCMaxMallocBytes(value);
}
void
JSRuntime::updateMallocCounter(size_t nbytes)
{
updateMallocCounter(NULL, nbytes);
}
void
JSRuntime::updateMallocCounter(JS::Zone *zone, size_t nbytes)
{
/* We tolerate any thread races when updating gcMallocBytes. */
ptrdiff_t oldCount = gcMallocBytes;
ptrdiff_t newCount = oldCount - ptrdiff_t(nbytes);
gcMallocBytes = newCount;
if (JS_UNLIKELY(newCount <= 0 && oldCount > 0))
onTooMuchMalloc();
else if (zone)
zone->updateMallocCounter(nbytes);
}
JS_FRIEND_API(void)
JSRuntime::onTooMuchMalloc()
{
TriggerGC(this, JS::gcreason::TOO_MUCH_MALLOC);
}
JS_FRIEND_API(void *)
JSRuntime::onOutOfMemory(void *p, size_t nbytes)
{
return onOutOfMemory(p, nbytes, NULL);
}
JS_FRIEND_API(void *)
JSRuntime::onOutOfMemory(void *p, size_t nbytes, JSContext *cx)
{
if (isHeapBusy())
return NULL;
/*
* Retry when we are done with the background sweeping and have stopped
* all the allocations and released the empty GC chunks.
*/
JS::ShrinkGCBuffers(this);
gcHelperThread.waitBackgroundSweepOrAllocEnd();
if (!p)
p = js_malloc(nbytes);
else if (p == reinterpret_cast<void *>(1))
p = js_calloc(nbytes);
else
p = js_realloc(p, nbytes);
if (p)
return p;
if (cx)
js_ReportOutOfMemory(cx);
return NULL;
}
static bool
ComputeIsJITBroken()
{

File diff suppressed because it is too large Load Diff

View File

@ -27,55 +27,6 @@
namespace js {
inline bool
NewObjectCache::lookupProto(Class *clasp, JSObject *proto, gc::AllocKind kind, EntryIndex *pentry)
{
JS_ASSERT(!proto->is<GlobalObject>());
return lookup(clasp, proto, kind, pentry);
}
inline bool
NewObjectCache::lookupGlobal(Class *clasp, js::GlobalObject *global, gc::AllocKind kind, EntryIndex *pentry)
{
return lookup(clasp, global, kind, pentry);
}
inline void
NewObjectCache::fillGlobal(EntryIndex entry, Class *clasp, js::GlobalObject *global, gc::AllocKind kind, JSObject *obj)
{
//JS_ASSERT(global == obj->getGlobal());
return fill(entry, clasp, global, kind, obj);
}
inline void
NewObjectCache::copyCachedToObject(JSObject *dst, JSObject *src, gc::AllocKind kind)
{
js_memcpy(dst, src, gc::Arena::thingSize(kind));
#ifdef JSGC_GENERATIONAL
Shape::writeBarrierPost(dst->shape_, &dst->shape_);
types::TypeObject::writeBarrierPost(dst->type_, &dst->type_);
#endif
}
inline JSObject *
NewObjectCache::newObjectFromHit(JSContext *cx, EntryIndex entry_, js::gc::InitialHeap heap)
{
// The new object cache does not account for metadata attached via callbacks.
JS_ASSERT(!cx->compartment()->objectMetadataCallback);
JS_ASSERT(unsigned(entry_) < mozilla::ArrayLength(entries));
Entry *entry = &entries[entry_];
JSObject *obj = js_NewGCObject<NoGC>(cx, entry->kind, heap);
if (obj) {
copyCachedToObject(obj, reinterpret_cast<JSObject *>(&entry->templateObject), entry->kind);
Probes::createObject(cx, obj);
return obj;
}
return NULL;
}
#ifdef JS_CRASH_DIAGNOSTICS
class CompartmentChecker
{

View File

@ -117,6 +117,7 @@ namespace js {
class AutoDebugModeGC;
class ArrayBufferObject;
class DebugScopes;
class WeakMapBase;
}
struct JSCompartment

View File

@ -9,7 +9,6 @@
#include "mozilla/DebugOnly.h"
#include "jsapi.h"
#include "jscntxt.h"
#include "jscompartment.h"
#include "jsgc.h"
#include "jsobj.h"
@ -17,6 +16,7 @@
#include "ion/BaselineJIT.h"
#include "ion/Ion.h"
#include "vm/Runtime.h"
#include "vm/Shape.h"
#include "jsobjinlines.h"

View File

@ -50,6 +50,7 @@
#include "vm/BooleanObject-inl.h"
#include "vm/NumberObject-inl.h"
#include "vm/RegExpStatics-inl.h"
#include "vm/Runtime-inl.h"
#include "vm/Shape-inl.h"
#include "vm/StringObject-inl.h"

View File

@ -31,7 +31,7 @@ class WeakCache : public HashMap<Key, Value, HashPolicy, AllocPolicy> {
public:
explicit WeakCache(JSRuntime *rt) : Base(rt) { }
explicit WeakCache(JSContext *cx) : Base(cx) { }
explicit WeakCache(JSContext *cx) : Base(cx->runtime()) { }
public:
// Sweep all entries which have unmarked key or value.
@ -82,7 +82,7 @@ class WeakValueCache : public HashMap<Key, Value, HashPolicy, AllocPolicy>
typedef typename Base::Enum Enum;
explicit WeakValueCache(JSRuntime *rt) : Base(rt) { }
explicit WeakValueCache(JSContext *cx) : Base(cx) { }
explicit WeakValueCache(JSContext *cx) : Base(cx->runtime()) { }
public:
// Sweep all entries which have unmarked key or value.

View File

@ -134,7 +134,7 @@ class WeakMap : public HashMap<Key, Value, HashPolicy, RuntimeAllocPolicy>, publ
typedef typename Base::Range Range;
explicit WeakMap(JSContext *cx, JSObject *memOf=NULL)
: Base(cx), WeakMapBase(memOf, cx->compartment()) { }
: Base(cx->runtime()), WeakMapBase(memOf, cx->compartment()) { }
private:
bool markValue(JSTracer *trc, Value *x) {

View File

@ -116,6 +116,7 @@ CPP_SOURCES += [
'RegExpObject.cpp',
'RegExpStatics.cpp',
'RootMarking.cpp',
'Runtime.cpp',
'SPSProfiler.cpp',
'ScopeObject.cpp',
'SelfHosting.cpp',

View File

@ -364,7 +364,7 @@ Breakpoint::nextInSite()
Debugger::Debugger(JSContext *cx, JSObject *dbg)
: object(dbg), uncaughtExceptionHook(NULL), enabled(true),
frames(cx), scripts(cx), sources(cx), objects(cx), environments(cx)
frames(cx->runtime()), scripts(cx), sources(cx), objects(cx), environments(cx)
{
assertSameCompartment(cx, dbg);
@ -2266,7 +2266,9 @@ class Debugger::ScriptQuery {
public:
/* Construct a ScriptQuery to use matching scripts for |dbg|. */
ScriptQuery(JSContext *cx, Debugger *dbg):
cx(cx), debugger(dbg), compartments(cx), url(cx), innermostForCompartment(cx) {}
cx(cx), debugger(dbg), compartments(cx->runtime()), url(cx),
innermostForCompartment(cx->runtime())
{}
/*
* Initialize this ScriptQuery. Raise an error and return false if we

View File

@ -51,7 +51,7 @@ class DebuggerWeakMap : private WeakMap<Key, Value, DefaultHasher<Key> >
public:
typedef WeakMap<Key, Value, DefaultHasher<Key> > Base;
explicit DebuggerWeakMap(JSContext *cx)
: Base(cx), zoneCounts(cx) { }
: Base(cx), zoneCounts(cx->runtime()) { }
public:
/* Expose those parts of HashMap public interface that are used by Debugger methods. */

View File

@ -18,7 +18,7 @@
#include "gc/Marking.h"
#include "js/TemplateLib.h"
#include "vm/MatchPairs.h"
#include "vm/Runtime.h"
#include "yarr/MatchResult.h"
#include "yarr/Yarr.h"
#if ENABLE_YARR_JIT

81
js/src/vm/Runtime-inl.h Normal file
View File

@ -0,0 +1,81 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* 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 vm_Runtime_inl_h
#define vm_Runtime_inl_h
#include "vm/Runtime.h"
#include "jscompartment.h"
#include "jsfriendapi.h"
#include "jsgc.h"
#include "jsiter.h"
#include "builtin/Object.h" // For js::obj_construct
#include "frontend/ParseMaps.h"
#include "ion/IonFrames.h" // For GetPcScript
#include "vm/Interpreter.h"
#include "vm/Probes.h"
#include "vm/RegExpObject.h"
#include "jsgcinlines.h"
#include "vm/ObjectImpl-inl.h"
namespace js {
inline bool
NewObjectCache::lookupProto(Class *clasp, JSObject *proto, gc::AllocKind kind, EntryIndex *pentry)
{
JS_ASSERT(!proto->is<GlobalObject>());
return lookup(clasp, proto, kind, pentry);
}
inline bool
NewObjectCache::lookupGlobal(Class *clasp, js::GlobalObject *global, gc::AllocKind kind, EntryIndex *pentry)
{
return lookup(clasp, global, kind, pentry);
}
inline void
NewObjectCache::fillGlobal(EntryIndex entry, Class *clasp, js::GlobalObject *global, gc::AllocKind kind, JSObject *obj)
{
//JS_ASSERT(global == obj->getGlobal());
return fill(entry, clasp, global, kind, obj);
}
inline void
NewObjectCache::copyCachedToObject(JSObject *dst, JSObject *src, gc::AllocKind kind)
{
js_memcpy(dst, src, gc::Arena::thingSize(kind));
#ifdef JSGC_GENERATIONAL
Shape::writeBarrierPost(dst->shape_, &dst->shape_);
types::TypeObject::writeBarrierPost(dst->type_, &dst->type_);
#endif
}
inline JSObject *
NewObjectCache::newObjectFromHit(JSContext *cx, EntryIndex entry_, js::gc::InitialHeap heap)
{
// The new object cache does not account for metadata attached via callbacks.
JS_ASSERT(!cx->compartment()->objectMetadataCallback);
JS_ASSERT(unsigned(entry_) < mozilla::ArrayLength(entries));
Entry *entry = &entries[entry_];
JSObject *obj = js_NewGCObject<NoGC>(cx, entry->kind, heap);
if (obj) {
copyCachedToObject(obj, reinterpret_cast<JSObject *>(&entry->templateObject), entry->kind);
Probes::createObject(cx, obj);
return obj;
}
return NULL;
}
} /* namespace js */
#endif /* vm_Runtime_inl_h */

264
js/src/vm/Runtime.cpp Normal file
View File

@ -0,0 +1,264 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* 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 "vm/Runtime.h"
#include <locale.h>
#include <string.h>
#include "mozilla/MemoryReporting.h"
#include "mozilla/Util.h"
#include "jsatom.h"
#include "jsgc.h"
#include "jsmath.h"
#include "jsobj.h"
#include "jsscript.h"
#include "js/MemoryMetrics.h"
#include "yarr/BumpPointerAllocator.h"
#include "jsgcinlines.h"
using namespace js;
using namespace js::gc;
using mozilla::PodZero;
void
NewObjectCache::clearNurseryObjects(JSRuntime *rt)
{
for (unsigned i = 0; i < mozilla::ArrayLength(entries); ++i) {
Entry &e = entries[i];
JSObject *obj = reinterpret_cast<JSObject *>(&e.templateObject);
if (IsInsideNursery(rt, e.key) ||
IsInsideNursery(rt, obj->slots) ||
IsInsideNursery(rt, obj->elements))
{
PodZero(&e);
}
}
}
void
JSRuntime::sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::RuntimeSizes *rtSizes)
{
rtSizes->object = mallocSizeOf(this);
rtSizes->atomsTable = atoms.sizeOfExcludingThis(mallocSizeOf);
rtSizes->contexts = 0;
for (ContextIter acx(this); !acx.done(); acx.next())
rtSizes->contexts += acx->sizeOfIncludingThis(mallocSizeOf);
rtSizes->dtoa = mallocSizeOf(mainThread.dtoaState);
rtSizes->temporary = tempLifoAlloc.sizeOfExcludingThis(mallocSizeOf);
rtSizes->code = JS::CodeSizes();
if (execAlloc_)
execAlloc_->sizeOfCode(&rtSizes->code);
rtSizes->regexpData = bumpAlloc_ ? bumpAlloc_->sizeOfNonHeapData() : 0;
rtSizes->interpreterStack = interpreterStack_.sizeOfExcludingThis(mallocSizeOf);
rtSizes->gcMarker = gcMarker.sizeOfExcludingThis(mallocSizeOf);
rtSizes->mathCache = mathCache_ ? mathCache_->sizeOfIncludingThis(mallocSizeOf) : 0;
rtSizes->scriptData = scriptDataTable.sizeOfExcludingThis(mallocSizeOf);
for (ScriptDataTable::Range r = scriptDataTable.all(); !r.empty(); r.popFront())
rtSizes->scriptData += mallocSizeOf(r.front());
}
void
JSRuntime::triggerOperationCallback()
{
AutoLockForOperationCallback lock(this);
/*
* Invalidate ionTop to trigger its over-recursion check. Note this must be
* set before interrupt, to avoid racing with js_InvokeOperationCallback,
* into a weird state where interrupt is stuck at 0 but ionStackLimit is
* MAXADDR.
*/
mainThread.setIonStackLimit(-1);
/*
* Use JS_ATOMIC_SET in the hope that it ensures the write will become
* immediately visible to other processors polling the flag.
*/
JS_ATOMIC_SET(&interrupt, 1);
#ifdef JS_ION
/* asm.js code uses a separate mechanism to halt running code. */
TriggerOperationCallbackForAsmJSCode(this);
#endif
}
void
JSRuntime::setJitHardening(bool enabled)
{
jitHardening = enabled;
if (execAlloc_)
execAlloc_->setRandomize(enabled);
}
JSC::ExecutableAllocator *
JSRuntime::createExecutableAllocator(JSContext *cx)
{
JS_ASSERT(!execAlloc_);
JS_ASSERT(cx->runtime() == this);
JSC::AllocationBehavior randomize =
jitHardening ? JSC::AllocationCanRandomize : JSC::AllocationDeterministic;
execAlloc_ = js_new<JSC::ExecutableAllocator>(randomize);
if (!execAlloc_)
js_ReportOutOfMemory(cx);
return execAlloc_;
}
WTF::BumpPointerAllocator *
JSRuntime::createBumpPointerAllocator(JSContext *cx)
{
JS_ASSERT(!bumpAlloc_);
JS_ASSERT(cx->runtime() == this);
bumpAlloc_ = js_new<WTF::BumpPointerAllocator>();
if (!bumpAlloc_)
js_ReportOutOfMemory(cx);
return bumpAlloc_;
}
MathCache *
JSRuntime::createMathCache(JSContext *cx)
{
JS_ASSERT(!mathCache_);
JS_ASSERT(cx->runtime() == this);
MathCache *newMathCache = js_new<MathCache>();
if (!newMathCache) {
js_ReportOutOfMemory(cx);
return NULL;
}
mathCache_ = newMathCache;
return mathCache_;
}
bool
JSRuntime::setDefaultLocale(const char *locale)
{
if (!locale)
return false;
resetDefaultLocale();
defaultLocale = JS_strdup(this, locale);
return defaultLocale != NULL;
}
void
JSRuntime::resetDefaultLocale()
{
js_free(defaultLocale);
defaultLocale = NULL;
}
const char *
JSRuntime::getDefaultLocale()
{
if (defaultLocale)
return defaultLocale;
char *locale, *lang, *p;
#ifdef HAVE_SETLOCALE
locale = setlocale(LC_ALL, NULL);
#else
locale = getenv("LANG");
#endif
// convert to a well-formed BCP 47 language tag
if (!locale || !strcmp(locale, "C"))
locale = const_cast<char*>("und");
lang = JS_strdup(this, locale);
if (!lang)
return NULL;
if ((p = strchr(lang, '.')))
*p = '\0';
while ((p = strchr(lang, '_')))
*p = '-';
defaultLocale = lang;
return defaultLocale;
}
void
JSRuntime::setGCMaxMallocBytes(size_t value)
{
/*
* For compatibility treat any value that exceeds PTRDIFF_T_MAX to
* mean that value.
*/
gcMaxMallocBytes = (ptrdiff_t(value) >= 0) ? value : size_t(-1) >> 1;
for (ZonesIter zone(this); !zone.done(); zone.next())
zone->setGCMaxMallocBytes(value);
}
void
JSRuntime::updateMallocCounter(size_t nbytes)
{
updateMallocCounter(NULL, nbytes);
}
void
JSRuntime::updateMallocCounter(JS::Zone *zone, size_t nbytes)
{
/* We tolerate any thread races when updating gcMallocBytes. */
ptrdiff_t oldCount = gcMallocBytes;
ptrdiff_t newCount = oldCount - ptrdiff_t(nbytes);
gcMallocBytes = newCount;
if (JS_UNLIKELY(newCount <= 0 && oldCount > 0))
onTooMuchMalloc();
else if (zone)
zone->updateMallocCounter(nbytes);
}
JS_FRIEND_API(void)
JSRuntime::onTooMuchMalloc()
{
TriggerGC(this, JS::gcreason::TOO_MUCH_MALLOC);
}
JS_FRIEND_API(void *)
JSRuntime::onOutOfMemory(void *p, size_t nbytes)
{
return onOutOfMemory(p, nbytes, NULL);
}
JS_FRIEND_API(void *)
JSRuntime::onOutOfMemory(void *p, size_t nbytes, JSContext *cx)
{
if (isHeapBusy())
return NULL;
/*
* Retry when we are done with the background sweeping and have stopped
* all the allocations and released the empty GC chunks.
*/
JS::ShrinkGCBuffers(this);
gcHelperThread.waitBackgroundSweepOrAllocEnd();
if (!p)
p = js_malloc(nbytes);
else if (p == reinterpret_cast<void *>(1))
p = js_calloc(nbytes);
else
p = js_realloc(p, nbytes);
if (p)
return p;
if (cx)
js_ReportOutOfMemory(cx);
return NULL;
}

1725
js/src/vm/Runtime.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1598,8 +1598,8 @@ js_IsDebugScopeSlow(JSObject *obj)
DebugScopes::DebugScopes(JSContext *cx)
: proxiedScopes(cx),
missingScopes(cx),
liveScopes(cx)
missingScopes(cx->runtime()),
liveScopes(cx->runtime())
{}
DebugScopes::~DebugScopes()

View File

@ -21,6 +21,7 @@
#include "jsobjinlines.h"
#include "vm/Shape-inl.h"
#include "vm/Runtime-inl.h"
using namespace js;
using namespace js::gc;

View File

@ -4,10 +4,10 @@
* 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 "jscntxt.h"
#include "jslock.h"
#include "vm/Monitor.h"
#include "vm/Runtime.h"
#include "vm/ThreadPool.h"
#ifdef JS_THREADSAFE

View File

@ -10,10 +10,10 @@
#include "jsprf.h"
#include "jsapi.h"
#include "jscntxt.h"
#include "jsscript.h"
#include "vm/Debugger.h"
#include "vm/Runtime.h"
#include "jsscriptinlines.h"

View File

@ -104,10 +104,10 @@ abstract public class BrowserApp extends GeckoApp
public int id;
public String label;
public String icon;
public boolean checkable;
public boolean checked;
public boolean enabled;
public boolean visible;
public boolean checkable = false;
public boolean checked = false;
public boolean enabled = true;
public boolean visible = true;
public int parent;
}
@ -985,21 +985,12 @@ abstract public class BrowserApp extends GeckoApp
MenuItemInfo info = new MenuItemInfo();
info.label = message.getString("name");
info.id = message.getInt("id") + ADDON_MENU_OFFSET;
info.checkable = false;
info.checked = false;
info.enabled = true;
info.visible = true;
String iconRes = null;
try { // icon is optional
iconRes = message.getString("icon");
} catch (Exception ex) { }
info.icon = iconRes;
try {
info.checkable = message.getBoolean("checkable");
} catch (Exception ex) { }
try { // parent is optional
info.parent = message.getInt("parent") + ADDON_MENU_OFFSET;
} catch (Exception ex) { }
info.icon = message.optString("icon", null);
info.checked = message.optBoolean("checked", false);
info.enabled = message.optBoolean("enabled", true);
info.visible = message.optBoolean("visible", true);
info.checkable = message.optBoolean("checkable", false);
info.parent = message.optInt("parent", -ADDON_MENU_OFFSET) + ADDON_MENU_OFFSET;
final MenuItemInfo menuItemInfo = info;
ThreadUtils.postToUiThread(new Runnable() {
@Override
@ -1489,21 +1480,10 @@ abstract public class BrowserApp extends GeckoApp
if (mAddonMenuItemsCache != null && !mAddonMenuItemsCache.isEmpty()) {
for (MenuItemInfo item : mAddonMenuItemsCache) {
if (item.id == id) {
try {
item.checkable = options.getBoolean("checkable");
} catch (JSONException e) {}
try {
item.checked = options.getBoolean("checked");
} catch (JSONException e) {}
try {
item.enabled = options.getBoolean("enabled");
} catch (JSONException e) {}
try {
item.visible = options.getBoolean("visible");
} catch (JSONException e) {}
item.checkable = options.optBoolean("checkable", item.checkable);
item.checked = options.optBoolean("checked", item.checked);
item.enabled = options.optBoolean("enabled", item.enabled);
item.visible = options.optBoolean("visible", item.visible);
break;
}
}
@ -1514,21 +1494,10 @@ abstract public class BrowserApp extends GeckoApp
MenuItem menuItem = mMenu.findItem(id);
if (menuItem != null) {
try {
menuItem.setCheckable(options.getBoolean("checkable"));
} catch (JSONException e) {}
try {
menuItem.setChecked(options.getBoolean("checked"));
} catch (JSONException e) {}
try {
menuItem.setEnabled(options.getBoolean("enabled"));
} catch (JSONException e) {}
try {
menuItem.setVisible(options.getBoolean("visible"));
} catch (JSONException e) {}
menuItem.setCheckable(options.optBoolean("checkable", menuItem.isCheckable()));
menuItem.setChecked(options.optBoolean("checked", menuItem.isChecked()));
menuItem.setEnabled(options.optBoolean("enabled", menuItem.isEnabled()));
menuItem.setVisible(options.optBoolean("visible", menuItem.isVisible()));
}
}

View File

@ -298,6 +298,18 @@ public class GeckoMenu extends ListView
if (item == null)
return;
// Remove it from any sub-menu.
for (GeckoMenuItem menuItem : mItems) {
if (menuItem.hasSubMenu()) {
SubMenu subMenu = menuItem.getSubMenu();
if (subMenu != null && subMenu.findItem(id) != null) {
subMenu.removeItem(id);
return;
}
}
}
// Remove it from own menu.
if (mActionItems.containsKey(item)) {
if (mActionItemBarPresenter != null)
mActionItemBarPresenter.removeActionItem(mActionItems.get(item));

View File

@ -32,8 +32,6 @@ public class GeckoMenuInflater extends MenuInflater {
private Context mContext;
private boolean isSubMenu;
// Private class to hold the parsed menu item.
private class ParsedItem {
public int id;
@ -45,13 +43,12 @@ public class GeckoMenuInflater extends MenuInflater {
public boolean visible;
public boolean enabled;
public int showAsAction;
public boolean hasSubMenu;
}
public GeckoMenuInflater(Context context) {
super(context);
mContext = context;
isSubMenu = false;
}
@Override
@ -64,58 +61,7 @@ public class GeckoMenuInflater extends MenuInflater {
parser = mContext.getResources().getXml(menuRes);
AttributeSet attrs = Xml.asAttributeSet(parser);
ParsedItem item = null;
SubMenu subMenu = null;
MenuItem menuItem = null;
String tag;
int eventType = parser.getEventType();
do {
tag = parser.getName();
switch (eventType) {
case XmlPullParser.START_TAG:
if (tag.equals(TAG_ITEM)) {
// Parse the menu item.
item = new ParsedItem();
parseItem(item, attrs);
} else if (tag.equals(TAG_MENU)) {
if (item != null) {
// Start parsing the sub menu.
isSubMenu = true;
subMenu = menu.addSubMenu(NO_ID, item.id, item.order, item.title);
menuItem = subMenu.getItem();
// Set the menu item in main menu.
setValues(item, menuItem);
}
}
break;
case XmlPullParser.END_TAG:
if (parser.getName().equals(TAG_ITEM)) {
if (isSubMenu && subMenu == null) {
isSubMenu = false;
} else {
// Add the item.
if (subMenu == null)
menuItem = menu.add(NO_ID, item.id, item.order, item.title);
else
menuItem = subMenu.add(NO_ID, item.id, item.order, item.title);
setValues(item, menuItem);
}
} else if (tag.equals(TAG_MENU)) {
// End of sub menu.
subMenu = null;
}
break;
}
eventType = parser.next();
} while (eventType != XmlPullParser.END_DOCUMENT);
parseMenu(parser, attrs, menu);
} catch (XmlPullParserException e) {
throw new InflateException("Error inflating menu XML", e);
@ -127,6 +73,56 @@ public class GeckoMenuInflater extends MenuInflater {
}
}
private void parseMenu(XmlResourceParser parser, AttributeSet attrs, Menu menu)
throws XmlPullParserException, IOException {
ParsedItem item = null;
String tag;
int eventType = parser.getEventType();
do {
tag = parser.getName();
switch (eventType) {
case XmlPullParser.START_TAG:
if (tag.equals(TAG_ITEM)) {
// Parse the menu item.
item = new ParsedItem();
parseItem(item, attrs);
} else if (tag.equals(TAG_MENU)) {
if (item != null) {
// Add the submenu item.
SubMenu subMenu = menu.addSubMenu(NO_ID, item.id, item.order, item.title);
item.hasSubMenu = true;
// Set the menu item in main menu.
MenuItem menuItem = subMenu.getItem();
setValues(item, menuItem);
// Start parsing the sub menu.
parseMenu(parser, attrs, subMenu);
}
}
break;
case XmlPullParser.END_TAG:
if (parser.getName().equals(TAG_ITEM)) {
if (!item.hasSubMenu) {
// Add the item.
MenuItem menuItem = menu.add(NO_ID, item.id, item.order, item.title);
setValues(item, menuItem);
}
} else if (tag.equals(TAG_MENU)) {
return;
}
break;
}
eventType = parser.next();
} while (eventType != XmlPullParser.END_DOCUMENT);
}
public void parseItem(ParsedItem item, AttributeSet attrs) {
TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.MenuItem);
@ -138,6 +134,7 @@ public class GeckoMenuInflater extends MenuInflater {
item.checked = a.getBoolean(R.styleable.MenuItem_android_checked, false);
item.visible = a.getBoolean(R.styleable.MenuItem_android_visible, true);
item.enabled = a.getBoolean(R.styleable.MenuItem_android_enabled, true);
item.hasSubMenu = false;
if (Build.VERSION.SDK_INT >= 11)
item.showAsAction = a.getInt(R.styleable.MenuItem_android_showAsAction, 0);

View File

@ -60,6 +60,7 @@
<item android:id="@+id/apps"
android:icon="@drawable/ic_menu_apps"
android:title="@string/apps"/>
</menu>
</item>

View File

@ -61,6 +61,7 @@
<item android:id="@+id/apps"
android:icon="@drawable/ic_menu_apps"
android:title="@string/apps"/>
</menu>
</item>

View File

@ -61,6 +61,7 @@
<item android:id="@+id/apps"
android:icon="@drawable/ic_menu_apps"
android:title="@string/apps"/>
</menu>
</item>

View File

@ -1761,12 +1761,10 @@
var initialString = (this.prefillWithSelection && userWantsPrefill) ?
this._getInitialSelection() : null;
if (initialString) {
if (initialString)
this._findField.value = initialString;
this._enableFindButtons(true);
}
else if (!this._findField.value)
this._enableFindButtons(false);
this._enableFindButtons(!!this._findField.value);
this._findField.select();
this._findField.focus();

View File

@ -84,11 +84,12 @@ class nsChildView;
class nsCocoaWindow;
union nsPluginPort;
namespace mozilla {
namespace gl {
class TextureImage;
namespace {
class GLPresenter;
class RectTextureImage;
}
namespace mozilla {
namespace layers {
class GLManager;
}
@ -572,6 +573,10 @@ public:
return nsCocoaUtils::DevPixelsToCocoaPoints(aRect, BackingScaleFactor());
}
mozilla::TemporaryRef<mozilla::gfx::DrawTarget> StartRemoteDrawing() MOZ_OVERRIDE;
void EndRemoteDrawing() MOZ_OVERRIDE;
void CleanupRemoteDrawing() MOZ_OVERRIDE;
protected:
void ReportMoveEvent();
@ -590,7 +595,10 @@ protected:
return widget.forget();
}
void DoRemoteComposition(const nsIntRect& aRenderRect);
// Overlay drawing functions for OpenGL drawing
void DrawWindowOverlay(mozilla::layers::GLManager* aManager, nsIntRect aRect);
void MaybeDrawResizeIndicator(mozilla::layers::GLManager* aManager, const nsIntRect& aRect);
void MaybeDrawRoundedCorners(mozilla::layers::GLManager* aManager, const nsIntRect& aRect);
void MaybeDrawTitlebar(mozilla::layers::GLManager* aManager, const nsIntRect& aRect);
@ -599,10 +607,6 @@ protected:
// determined by mDirtyTitlebarRegion.
void UpdateTitlebarImageBuffer();
// Upload the contents of mTitlebarImageBuffer to mTitlebarImage on the
// compositor thread, as determined by mUpdatedTitlebarRegion.
void UpdateTitlebarImage(mozilla::layers::GLManager* aManager, const nsIntRect& aRect);
nsIntRect RectContainingTitlebarControls();
nsIWidget* GetWidgetForListenerEvents();
@ -640,14 +644,13 @@ protected:
// transaction. Accessed from any thread, protected by mEffectsLock.
nsIntRegion mUpdatedTitlebarRegion;
nsRefPtr<gfxQuartzSurface> mTitlebarImageBuffer;
mozilla::RefPtr<mozilla::gfx::DrawTarget> mTitlebarImageBuffer;
// Compositor thread only
bool mFailedResizerImage;
bool mFailedCornerMaskImage;
nsRefPtr<mozilla::gl::TextureImage> mResizerImage;
nsRefPtr<mozilla::gl::TextureImage> mCornerMaskImage;
nsRefPtr<mozilla::gl::TextureImage> mTitlebarImage;
nsAutoPtr<RectTextureImage> mResizerImage;
nsAutoPtr<RectTextureImage> mCornerMaskImage;
nsAutoPtr<RectTextureImage> mTitlebarImage;
nsAutoPtr<RectTextureImage> mBasicCompositorImage;
// The area of mTitlebarImageBuffer that has changed and needs to be
// uploaded to to mTitlebarImage. Main thread only.
@ -667,6 +670,10 @@ protected:
NP_CGContext mPluginCGContext;
nsIPluginInstanceOwner* mPluginInstanceOwner; // [WEAK]
// Used in OMTC BasicLayers mode. Presents the BasicCompositor result
// surface to the screen using an OpenGL context.
nsAutoPtr<GLPresenter> mGLPresenter;
static uint32_t sLastInputEventCount;
};

View File

@ -55,9 +55,13 @@
#include "ClientLayerManager.h"
#include "mozilla/layers/LayerManagerComposite.h"
#include "GLTextureImage.h"
#include "GLContextProvider.h"
#include "mozilla/layers/GLManager.h"
#include "mozilla/layers/CompositorCocoaWidgetHelper.h"
#include "mozilla/layers/CompositorOGL.h"
#include "mozilla/layers/BasicCompositor.h"
#include "gfxUtils.h"
#include "mozilla/gfx/2D.h"
#ifdef ACCESSIBILITY
#include "nsAccessibilityService.h"
#include "mozilla/a11y/Platform.h"
@ -243,6 +247,108 @@ void EnsureLogInitialized()
#endif // PR_LOGGING
}
namespace {
// Manages a texture which can resize dynamically, binds to the
// LOCAL_GL_TEXTURE_RECTANGLE_ARB texture target and is automatically backed
// by a power-of-two size GL texture. The latter two features are used for
// compatibility with older Mac hardware which we block GL layers on.
// RectTextureImages are used both for accelerated GL layers drawing and for
// OMTC BasicLayers drawing.
class RectTextureImage {
public:
RectTextureImage(GLContext* aGLContext)
: mGLContext(aGLContext)
, mTexture(0)
, mInUpdate(false)
{}
virtual ~RectTextureImage();
TemporaryRef<gfx::DrawTarget>
BeginUpdate(const nsIntSize& aNewSize,
const nsIntRegion& aDirtyRegion = nsIntRegion());
void EndUpdate(bool aKeepSurface = false);
void UpdateIfNeeded(const nsIntSize& aNewSize,
const nsIntRegion& aDirtyRegion,
void (^aCallback)(gfx::DrawTarget*, const nsIntRegion&))
{
RefPtr<gfx::DrawTarget> drawTarget = BeginUpdate(aNewSize, aDirtyRegion);
if (drawTarget) {
aCallback(drawTarget, GetUpdateRegion());
EndUpdate();
}
}
void UpdateFromDrawTarget(const nsIntSize& aNewSize,
const nsIntRegion& aDirtyRegion,
gfx::DrawTarget* aFromDrawTarget);
nsIntRegion GetUpdateRegion() {
MOZ_ASSERT(mInUpdate, "update region only valid during update");
return mUpdateRegion;
}
void Draw(mozilla::layers::GLManager* aManager,
const nsIntPoint& aLocation,
const gfx3DMatrix& aTransform = gfx3DMatrix());
static nsIntSize TextureSizeForSize(const nsIntSize& aSize);
protected:
RefPtr<gfx::DrawTarget> mUpdateDrawTarget;
GLContext* mGLContext;
nsIntRegion mUpdateRegion;
nsIntSize mUsedSize;
nsIntSize mBufferSize;
nsIntSize mTextureSize;
GLuint mTexture;
bool mInUpdate;
};
// Used for OpenGL drawing from the compositor thread for OMTC BasicLayers.
// We need to use OpenGL for this because there seems to be no other robust
// way of drawing from a secondary thread without locking, which would cause
// deadlocks in our setup. See bug 882523.
class GLPresenter : public GLManager
{
public:
static GLPresenter* CreateForWindow(nsIWidget* aWindow)
{
nsRefPtr<GLContext> context = gl::GLContextProvider::CreateForWindow(aWindow);
return context ? new GLPresenter(context) : nullptr;
}
GLPresenter(GLContext* aContext);
virtual ~GLPresenter();
virtual GLContext* gl() const MOZ_OVERRIDE { return mGLContext; }
virtual ShaderProgramOGL* GetProgram(ShaderProgramType aType) MOZ_OVERRIDE
{
MOZ_ASSERT(aType == BGRARectLayerProgramType, "unexpected program type");
return mBGRARectProgram;
}
virtual void BindAndDrawQuad(ShaderProgramOGL *aProg) MOZ_OVERRIDE;
void BeginFrame(nsIntSize aRenderSize);
void EndFrame();
NSOpenGLContext* GetNSOpenGLContext()
{
return static_cast<NSOpenGLContext*>(
mGLContext->GetNativeData(GLContext::NativeGLContext));
}
protected:
nsRefPtr<mozilla::gl::GLContext> mGLContext;
nsAutoPtr<mozilla::layers::ShaderProgramOGL> mBGRARectProgram;
GLuint mQuadVBO;
};
} // unnamed namespace
#pragma mark -
nsChildView::nsChildView() : nsBaseWidget()
@ -253,8 +359,6 @@ nsChildView::nsChildView() : nsBaseWidget()
, mShowsResizeIndicator(false)
, mHasRoundedBottomCorners(false)
, mIsCoveringTitlebar(false)
, mFailedResizerImage(false)
, mFailedCornerMaskImage(false)
, mBackingScaleFactor(0.0)
, mVisible(false)
, mDrawing(false)
@ -1387,8 +1491,7 @@ NS_IMETHODIMP nsChildView::Invalidate(const nsIntRect &aRect)
if (!mView || !mVisible)
return NS_OK;
NS_ASSERTION(GetLayerManager()->GetBackendType() != LAYERS_CLIENT ||
Compositor::GetBackend() == LAYERS_BASIC,
NS_ASSERTION(GetLayerManager()->GetBackendType() != LAYERS_CLIENT,
"Shouldn't need to invalidate with accelerated OMTC layers!");
if ([NSView focusView]) {
@ -1419,11 +1522,20 @@ nsChildView::ComputeShouldAccelerate(bool aDefault)
bool
nsChildView::ShouldUseOffMainThreadCompositing()
{
// OMTC doesn't work with Basic Layers on OS X right now. Once it works, we'll
// still want to disable it for certain kinds of windows (e.g. popups).
return nsBaseWidget::ShouldUseOffMainThreadCompositing() &&
(ComputeShouldAccelerate(mUseLayersAcceleration) ||
Preferences::GetBool("layers.offmainthreadcomposition.prefer-basic", false));
// When acceleration is off, default to false, but allow force-enabling
// using the layers.offmainthreadcomposition.prefer-basic pref.
if (!ComputeShouldAccelerate(mUseLayersAcceleration) &&
!Preferences::GetBool("layers.offmainthreadcomposition.prefer-basic", false)) {
return false;
}
// Don't use OMTC (which requires OpenGL) for transparent windows or for
// popup windows.
if (!mView || ![[mView window] isOpaque] ||
[[mView window] isKindOfClass:[PopupWindow class]])
return false;
return nsBaseWidget::ShouldUseOffMainThreadCompositing();
}
inline uint16_t COLOR8TOCOLOR16(uint8_t color8)
@ -1908,26 +2020,25 @@ void
nsChildView::DrawWindowOverlay(LayerManager* aManager, nsIntRect aRect)
{
nsAutoPtr<GLManager> manager(GLManager::CreateGLManager(aManager));
if (!manager) {
return;
if (manager) {
DrawWindowOverlay(manager, aRect);
}
}
manager->gl()->PushScissorRect(aRect);
MaybeDrawTitlebar(manager, aRect);
MaybeDrawResizeIndicator(manager, aRect);
MaybeDrawRoundedCorners(manager, aRect);
manager->gl()->PopScissorRect();
void
nsChildView::DrawWindowOverlay(GLManager* aManager, nsIntRect aRect)
{
MaybeDrawTitlebar(aManager, aRect);
MaybeDrawResizeIndicator(aManager, aRect);
MaybeDrawRoundedCorners(aManager, aRect);
}
static void
ClearRegion(gfxASurface* aSurface, nsIntRegion aRegion)
ClearRegion(gfx::DrawTarget *aDT, nsIntRegion aRegion)
{
nsRefPtr<gfxContext> ctx = new gfxContext(aSurface);
gfxUtils::ClipToRegion(ctx, aRegion);
ctx->SetOperator(gfxContext::OPERATOR_CLEAR);
ctx->Paint();
gfxUtils::ClipToRegion(aDT, aRegion);
aDT->ClearRect(gfx::Rect(0, 0, aDT->GetSize().width, aDT->GetSize().height));
aDT->PopClip();
}
static void
@ -1967,66 +2078,21 @@ void
nsChildView::MaybeDrawResizeIndicator(GLManager* aManager, const nsIntRect& aRect)
{
MutexAutoLock lock(mEffectsLock);
if (!mShowsResizeIndicator || mFailedResizerImage) {
if (!mShowsResizeIndicator) {
return;
}
if (!mResizerImage) {
mResizerImage =
aManager->gl()->CreateTextureImage(nsIntSize(mResizeIndicatorRect.width,
mResizeIndicatorRect.height),
gfxASurface::CONTENT_COLOR_ALPHA,
LOCAL_GL_CLAMP_TO_EDGE,
TextureImage::UseNearestFilter);
// Creation of texture images can fail.
if (!mResizerImage)
return;
nsIntRegion update(nsIntRect(0, 0, mResizeIndicatorRect.width, mResizeIndicatorRect.height));
gfxASurface *asurf = mResizerImage->BeginUpdate(update);
if (!asurf) {
mResizerImage = nullptr;
return;
}
// We need a Quartz surface because DrawResizer wants a CGContext.
if (asurf->GetType() != gfxASurface::SurfaceTypeQuartz) {
NS_WARN_IF_FALSE(FALSE, "mResizerImage's surface is not Quartz");
mResizerImage->EndUpdate();
mResizerImage = nullptr;
mFailedResizerImage = true;
return;
}
ClearRegion(asurf, update);
nsRefPtr<gfxQuartzSurface> image = static_cast<gfxQuartzSurface*>(asurf);
DrawResizer(image->GetCGContext());
mResizerImage->EndUpdate();
mResizerImage = new RectTextureImage(aManager->gl());
}
NS_ABORT_IF_FALSE(mResizerImage, "Must have a texture allocated by now!");
nsIntSize size = mResizeIndicatorRect.Size();
mResizerImage->UpdateIfNeeded(size, nsIntRegion(), ^(gfx::DrawTarget* drawTarget, const nsIntRegion& updateRegion) {
ClearRegion(drawTarget, updateRegion);
DrawResizer(static_cast<CGContextRef>(drawTarget->GetNativeSurface(gfx::NATIVE_SURFACE_CGCONTEXT)));
});
float bottomX = aRect.XMost();
float bottomY = aRect.YMost();
TextureImage::ScopedBindTexture texBind(mResizerImage, LOCAL_GL_TEXTURE0);
ShaderProgramOGL *program =
aManager->GetProgram(mResizerImage->GetTextureFormat());
program->Activate();
program->SetLayerQuadRect(nsIntRect(bottomX - resizeIndicatorWidth,
bottomY - resizeIndicatorHeight,
resizeIndicatorWidth,
resizeIndicatorHeight));
program->SetLayerTransform(gfx3DMatrix());
program->SetLayerOpacity(1.0);
program->SetRenderOffset(nsIntPoint(0,0));
program->SetTextureUnit(0);
aManager->BindAndDrawQuad(program);
mResizerImage->Draw(aManager, mResizeIndicatorRect.TopLeft());
}
// Draw the highlight line at the top of the titlebar.
@ -2066,12 +2132,16 @@ nsChildView::UpdateTitlebarImageBuffer()
nsIntRegion dirtyTitlebarRegion = mDirtyTitlebarRegion;
mDirtyTitlebarRegion.SetEmpty();
nsIntSize texSize = RectTextureImage::TextureSizeForSize(mTitlebarRect.Size());
gfx::IntSize titlebarBufferSize(texSize.width, texSize.height);
if (!mTitlebarImageBuffer ||
mTitlebarImageBuffer->GetSize() != mTitlebarRect.Size()) {
mTitlebarImageBuffer->GetSize() != titlebarBufferSize) {
dirtyTitlebarRegion = mTitlebarRect;
mTitlebarImageBuffer = new gfxQuartzSurface(mTitlebarRect.Size(),
gfxASurface::ImageFormatARGB32);
mTitlebarImageBuffer =
gfx::Factory::CreateDrawTarget(gfx::BACKEND_COREGRAPHICS,
titlebarBufferSize,
gfx::FORMAT_B8G8R8A8);
}
if (dirtyTitlebarRegion.IsEmpty())
@ -2079,7 +2149,8 @@ nsChildView::UpdateTitlebarImageBuffer()
ClearRegion(mTitlebarImageBuffer, dirtyTitlebarRegion);
CGContextRef ctx = mTitlebarImageBuffer->GetCGContext();
CGContextRef ctx =
static_cast<CGContextRef>(mTitlebarImageBuffer->GetNativeSurface(gfx::NATIVE_SURFACE_CGCONTEXT));
CGContextSaveGState(ctx);
double scale = BackingScaleFactor();
@ -2151,45 +2222,6 @@ nsChildView::UpdateTitlebarImageBuffer()
mUpdatedTitlebarRegion.Or(mUpdatedTitlebarRegion, dirtyTitlebarRegion);
}
// When this method is entered, mEffectsLock is already being held.
void
nsChildView::UpdateTitlebarImage(GLManager* aManager, const nsIntRect& aRect)
{
nsIntRegion updatedTitlebarRegion;
updatedTitlebarRegion.And(mUpdatedTitlebarRegion, mTitlebarRect);
mUpdatedTitlebarRegion.SetEmpty();
if (!mTitlebarImage || mTitlebarImage->GetSize() != mTitlebarRect.Size()) {
updatedTitlebarRegion = mTitlebarRect;
mTitlebarImage =
aManager->gl()->CreateTextureImage(mTitlebarRect.Size(),
gfxASurface::CONTENT_COLOR_ALPHA,
LOCAL_GL_CLAMP_TO_EDGE,
TextureImage::UseNearestFilter);
// Creation of texture images can fail.
if (!mTitlebarImage)
return;
}
if (updatedTitlebarRegion.IsEmpty())
return;
gfxASurface *asurf = mTitlebarImage->BeginUpdate(updatedTitlebarRegion);
if (!asurf) {
mTitlebarImage = nullptr;
return;
}
nsRefPtr<gfxContext> ctx = new gfxContext(asurf);
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
ctx->SetSource(mTitlebarImageBuffer);
ctx->Paint();
mTitlebarImage->EndUpdate();
}
// This method draws an overlay in the top of the window which contains the
// titlebar controls (e.g. close, min, zoom, fullscreen) and the titlebar
// highlight effect.
@ -2208,25 +2240,19 @@ nsChildView::MaybeDrawTitlebar(GLManager* aManager, const nsIntRect& aRect)
return;
}
UpdateTitlebarImage(aManager, aRect);
nsIntRegion updatedTitlebarRegion;
updatedTitlebarRegion.And(mUpdatedTitlebarRegion, mTitlebarRect);
mUpdatedTitlebarRegion.SetEmpty();
if (!mTitlebarImage) {
return;
mTitlebarImage = new RectTextureImage(aManager->gl());
}
TextureImage::ScopedBindTexture texBind(mTitlebarImage, LOCAL_GL_TEXTURE0);
mTitlebarImage->UpdateFromDrawTarget(mTitlebarRect.Size(),
updatedTitlebarRegion,
mTitlebarImageBuffer);
ShaderProgramOGL *program =
aManager->GetProgram(mTitlebarImage->GetTextureFormat());
program->Activate();
program->SetLayerQuadRect(nsIntRect(nsIntPoint(0, 0),
mTitlebarImage->GetSize()));
program->SetLayerTransform(gfx3DMatrix());
program->SetLayerOpacity(1.0);
program->SetRenderOffset(nsIntPoint(0,0));
program->SetTextureUnit(0);
aManager->BindAndDrawQuad(program);
mTitlebarImage->Draw(aManager, mTitlebarRect.TopLeft());
}
static void
@ -2240,81 +2266,35 @@ void
nsChildView::MaybeDrawRoundedCorners(GLManager* aManager, const nsIntRect& aRect)
{
MutexAutoLock lock(mEffectsLock);
if (mFailedCornerMaskImage) {
return;
if (!mCornerMaskImage) {
mCornerMaskImage = new RectTextureImage(aManager->gl());
}
if (!mCornerMaskImage ||
mCornerMaskImage->GetSize().width != mDevPixelCornerRadius) {
mCornerMaskImage =
aManager->gl()->CreateTextureImage(nsIntSize(mDevPixelCornerRadius,
mDevPixelCornerRadius),
gfxASurface::CONTENT_COLOR_ALPHA,
LOCAL_GL_CLAMP_TO_EDGE,
TextureImage::UseNearestFilter);
// Creation of texture images can fail.
if (!mCornerMaskImage)
return;
nsIntRegion update(nsIntRect(0, 0, mDevPixelCornerRadius, mDevPixelCornerRadius));
gfxASurface *asurf = mCornerMaskImage->BeginUpdate(update);
if (!asurf) {
mCornerMaskImage = nullptr;
return;
}
if (asurf->GetType() != gfxASurface::SurfaceTypeQuartz) {
NS_WARNING("mCornerMaskImage's surface is not Quartz");
mCornerMaskImage->EndUpdate();
mCornerMaskImage = nullptr;
mFailedCornerMaskImage = true;
return;
}
ClearRegion(asurf, update);
nsRefPtr<gfxQuartzSurface> image = static_cast<gfxQuartzSurface*>(asurf);
DrawTopLeftCornerMask(image->GetCGContext(), mDevPixelCornerRadius);
mCornerMaskImage->EndUpdate();
}
NS_ABORT_IF_FALSE(mCornerMaskImage, "Must have a texture allocated by now!");
TextureImage::ScopedBindTexture texBind(mCornerMaskImage, LOCAL_GL_TEXTURE0);
ShaderProgramOGL *program = aManager->GetProgram(mCornerMaskImage->GetTextureFormat());
program->Activate();
program->SetLayerQuadRect(nsIntRect(nsIntPoint(0, 0),
mCornerMaskImage->GetSize()));
program->SetLayerOpacity(1.0);
program->SetRenderOffset(nsIntPoint(0,0));
program->SetTextureUnit(0);
nsIntSize size(mDevPixelCornerRadius, mDevPixelCornerRadius);
mCornerMaskImage->UpdateIfNeeded(size, nsIntRegion(), ^(gfx::DrawTarget* drawTarget, const nsIntRegion& updateRegion) {
ClearRegion(drawTarget, updateRegion);
DrawTopLeftCornerMask(static_cast<CGContextRef>(drawTarget->GetNativeSurface(gfx::NATIVE_SURFACE_CGCONTEXT)),
mDevPixelCornerRadius);
});
// Use operator destination in: multiply all 4 channels with source alpha.
aManager->gl()->fBlendFuncSeparate(LOCAL_GL_ZERO, LOCAL_GL_SRC_ALPHA,
LOCAL_GL_ZERO, LOCAL_GL_SRC_ALPHA);
gfx3DMatrix flipX = gfx3DMatrix::ScalingMatrix(-1, 1, 1);
gfx3DMatrix flipY = gfx3DMatrix::ScalingMatrix(1, -1, 1);
if (mIsCoveringTitlebar) {
// Mask the top corners.
program->SetLayerTransform(gfx3DMatrix::ScalingMatrix(1, 1, 1) *
gfx3DMatrix::Translation(0, 0, 0));
aManager->BindAndDrawQuad(program);
program->SetLayerTransform(gfx3DMatrix::ScalingMatrix(-1, 1, 1) *
gfx3DMatrix::Translation(aRect.width, 0, 0));
aManager->BindAndDrawQuad(program);
mCornerMaskImage->Draw(aManager, aRect.TopLeft());
mCornerMaskImage->Draw(aManager, aRect.TopRight(), flipX);
}
if (mHasRoundedBottomCorners) {
// Mask the bottom corners.
program->SetLayerTransform(gfx3DMatrix::ScalingMatrix(1, -1, 1) *
gfx3DMatrix::Translation(0, aRect.height, 0));
aManager->BindAndDrawQuad(program);
program->SetLayerTransform(gfx3DMatrix::ScalingMatrix(-1, -1, 1) *
gfx3DMatrix::Translation(aRect.width, aRect.height, 0));
aManager->BindAndDrawQuad(program);
mCornerMaskImage->Draw(aManager, aRect.BottomLeft(), flipY);
mCornerMaskImage->Draw(aManager, aRect.BottomRight(), flipY * flipX);
}
// Reset blend mode.
@ -2376,6 +2356,69 @@ nsChildView::UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometri
[win setUnifiedToolbarHeight:DevPixelsToCocoaPoints(devUnifiedHeight)];
}
TemporaryRef<gfx::DrawTarget>
nsChildView::StartRemoteDrawing()
{
if (!mGLPresenter) {
mGLPresenter = GLPresenter::CreateForWindow(this);
if (!mGLPresenter) {
return nullptr;
}
}
nsIntRegion dirtyRegion = mBounds;
nsIntSize renderSize = mBounds.Size();
if (!mBasicCompositorImage) {
mBasicCompositorImage = new RectTextureImage(mGLPresenter->gl());
}
RefPtr<gfx::DrawTarget> drawTarget =
mBasicCompositorImage->BeginUpdate(renderSize, dirtyRegion);
if (!drawTarget) {
// Composite unchanged textures.
DoRemoteComposition(mBounds);
return nullptr;
}
return drawTarget;
}
void
nsChildView::EndRemoteDrawing()
{
mBasicCompositorImage->EndUpdate(true);
DoRemoteComposition(mBounds);
}
void
nsChildView::CleanupRemoteDrawing()
{
mBasicCompositorImage = nullptr;
mCornerMaskImage = nullptr;
mResizerImage = nullptr;
mTitlebarImage = nullptr;
mGLPresenter = nullptr;
}
void
nsChildView::DoRemoteComposition(const nsIntRect& aRenderRect)
{
[(ChildView*)mView preRender:mGLPresenter->GetNSOpenGLContext()];
mGLPresenter->BeginFrame(aRenderRect.Size());
// Draw the result from the basic compositor.
mBasicCompositorImage->Draw(mGLPresenter, nsIntPoint(0, 0));
// DrawWindowOverlay doesn't do anything for non-GL, so it didn't paint
// anything during the basic compositor transaction. Draw the overlay now.
DrawWindowOverlay(mGLPresenter, aRenderRect);
mGLPresenter->EndFrame();
}
#ifdef ACCESSIBILITY
already_AddRefed<a11y::Accessible>
nsChildView::GetDocumentAccessible()
@ -2399,6 +2442,234 @@ nsChildView::GetDocumentAccessible()
}
#endif
// RectTextureImage implementation
RectTextureImage::~RectTextureImage()
{
if (mTexture) {
mGLContext->MakeCurrent();
mGLContext->fDeleteTextures(1, &mTexture);
mTexture = 0;
}
}
nsIntSize
RectTextureImage::TextureSizeForSize(const nsIntSize& aSize)
{
return nsIntSize(gfx::NextPowerOfTwo(aSize.width),
gfx::NextPowerOfTwo(aSize.height));
}
TemporaryRef<gfx::DrawTarget>
RectTextureImage::BeginUpdate(const nsIntSize& aNewSize,
const nsIntRegion& aDirtyRegion)
{
MOZ_ASSERT(!mInUpdate, "Beginning update during update!");
mUpdateRegion = aDirtyRegion;
if (aNewSize != mUsedSize) {
mUsedSize = aNewSize;
mUpdateRegion = nsIntRect(nsIntPoint(0, 0), aNewSize);
}
if (mUpdateRegion.IsEmpty()) {
return nullptr;
}
nsIntSize neededBufferSize = TextureSizeForSize(mUsedSize);
if (!mUpdateDrawTarget || mBufferSize != neededBufferSize) {
gfx::IntSize size(neededBufferSize.width, neededBufferSize.height);
mUpdateDrawTarget =
gfx::Factory::CreateDrawTarget(gfx::BACKEND_COREGRAPHICS, size,
gfx::FORMAT_B8G8R8A8);
mBufferSize = neededBufferSize;
}
mInUpdate = true;
RefPtr<gfx::DrawTarget> drawTarget = mUpdateDrawTarget;
return drawTarget;
}
#define NSFoundationVersionWithProperStrideSupportForSubtextureUpload NSFoundationVersionNumber10_6_3
static bool
CanUploadSubtextures()
{
return NSFoundationVersionNumber >= NSFoundationVersionWithProperStrideSupportForSubtextureUpload;
}
void
RectTextureImage::EndUpdate(bool aKeepSurface)
{
MOZ_ASSERT(mInUpdate, "Ending update while not in update");
bool overwriteTexture = false;
nsIntRegion updateRegion = mUpdateRegion;
if (!mTexture || (mTextureSize != mBufferSize)) {
overwriteTexture = true;
mTextureSize = mBufferSize;
}
if (overwriteTexture || !CanUploadSubtextures()) {
updateRegion = nsIntRect(nsIntPoint(0, 0), mTextureSize);
}
RefPtr<gfx::SourceSurface> snapshot = mUpdateDrawTarget->Snapshot();
RefPtr<gfx::DataSourceSurface> dataSnapshot = snapshot->GetDataSurface();
mGLContext->UploadSurfaceToTexture(dataSnapshot,
updateRegion,
mTexture,
overwriteTexture,
updateRegion.GetBounds().TopLeft(),
false,
LOCAL_GL_TEXTURE0,
LOCAL_GL_TEXTURE_RECTANGLE_ARB);
if (!aKeepSurface) {
mUpdateDrawTarget = nullptr;
}
mInUpdate = false;
}
void
RectTextureImage::UpdateFromDrawTarget(const nsIntSize& aNewSize,
const nsIntRegion& aDirtyRegion,
gfx::DrawTarget* aFromDrawTarget)
{
mUpdateDrawTarget = aFromDrawTarget;
mBufferSize.SizeTo(aFromDrawTarget->GetSize().width, aFromDrawTarget->GetSize().height);
RefPtr<gfx::DrawTarget> drawTarget = BeginUpdate(aNewSize, aDirtyRegion);
if (drawTarget) {
if (drawTarget != aFromDrawTarget) {
RefPtr<gfx::SourceSurface> source = aFromDrawTarget->Snapshot();
gfx::Rect rect(0, 0, aFromDrawTarget->GetSize().width, aFromDrawTarget->GetSize().height);
gfxUtils::ClipToRegion(drawTarget, GetUpdateRegion());
drawTarget->DrawSurface(source, rect, rect,
gfx::DrawSurfaceOptions(),
gfx::DrawOptions(1.0, gfx::OP_SOURCE));
drawTarget->PopClip();
}
EndUpdate();
}
mUpdateDrawTarget = nullptr;
}
void
RectTextureImage::Draw(GLManager* aManager,
const nsIntPoint& aLocation,
const gfx3DMatrix& aTransform)
{
ShaderProgramOGL* program = aManager->GetProgram(BGRARectLayerProgramType);
aManager->gl()->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, mTexture);
program->Activate();
program->SetLayerQuadRect(nsIntRect(nsIntPoint(0, 0), mUsedSize));
program->SetLayerTransform(aTransform * gfx3DMatrix::Translation(aLocation.x, aLocation.y, 0));
program->SetLayerOpacity(1.0);
program->SetRenderOffset(nsIntPoint(0, 0));
program->SetTexCoordMultiplier(mUsedSize.width, mUsedSize.height);
program->SetTextureUnit(0);
aManager->BindAndDrawQuad(program);
aManager->gl()->fBindTexture(LOCAL_GL_TEXTURE_RECTANGLE_ARB, 0);
}
// GLPresenter implementation
GLPresenter::GLPresenter(GLContext* aContext)
: mGLContext(aContext)
{
mGLContext->SetFlipped(true);
mGLContext->MakeCurrent();
mBGRARectProgram = new ShaderProgramOGL(mGLContext,
ProgramProfileOGL::GetProfileFor(BGRARectLayerProgramType, MaskNone));
// Create mQuadVBO.
mGLContext->fGenBuffers(1, &mQuadVBO);
mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mQuadVBO);
GLfloat vertices[] = {
/* First quad vertices */
0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
/* Then quad texcoords */
0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
};
mGLContext->fBufferData(LOCAL_GL_ARRAY_BUFFER, sizeof(vertices), vertices, LOCAL_GL_STATIC_DRAW);
mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
}
GLPresenter::~GLPresenter()
{
if (mQuadVBO) {
mGLContext->MakeCurrent();
mGLContext->fDeleteBuffers(1, &mQuadVBO);
mQuadVBO = 0;
}
}
void
GLPresenter::BindAndDrawQuad(ShaderProgramOGL* aProgram)
{
mGLContext->MakeCurrent();
GLuint vertAttribIndex = aProgram->AttribLocation(ShaderProgramOGL::VertexCoordAttrib);
GLuint texCoordAttribIndex = aProgram->AttribLocation(ShaderProgramOGL::TexCoordAttrib);
mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mQuadVBO);
mGLContext->fVertexAttribPointer(vertAttribIndex, 2,
LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0,
(GLvoid*)0);
mGLContext->fEnableVertexAttribArray(vertAttribIndex);
mGLContext->fVertexAttribPointer(texCoordAttribIndex, 2,
LOCAL_GL_FLOAT, LOCAL_GL_FALSE, 0,
(GLvoid*) (sizeof(float)*4*2));
mGLContext->fEnableVertexAttribArray(texCoordAttribIndex);
mGLContext->fDrawArrays(LOCAL_GL_TRIANGLE_STRIP, 0, 4);
mGLContext->fDisableVertexAttribArray(vertAttribIndex);
mGLContext->fDisableVertexAttribArray(texCoordAttribIndex);
}
void
GLPresenter::BeginFrame(nsIntSize aRenderSize)
{
mGLContext->MakeCurrent();
mGLContext->fViewport(0, 0, aRenderSize.width, aRenderSize.height);
// Matrix to transform (0, 0, width, height) to viewport space (-1.0, 1.0,
// 2, 2) and flip the contents.
gfxMatrix viewMatrix;
viewMatrix.Translate(-gfxPoint(1.0, -1.0));
viewMatrix.Scale(2.0f / float(aRenderSize.width), 2.0f / float(aRenderSize.height));
viewMatrix.Scale(1.0f, -1.0f);
gfx3DMatrix matrix3d = gfx3DMatrix::From2D(viewMatrix);
matrix3d._33 = 0.0f;
mBGRARectProgram->CheckAndSetProjectionMatrix(matrix3d);
// Default blend function implements "OVER"
mGLContext->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA,
LOCAL_GL_ONE, LOCAL_GL_ONE);
mGLContext->fEnable(LOCAL_GL_BLEND);
mGLContext->fClearColor(0.0, 0.0, 0.0, 0.0);
mGLContext->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT);
mGLContext->fEnable(LOCAL_GL_TEXTURE_RECTANGLE_ARB);
}
void
GLPresenter::EndFrame()
{
mGLContext->SwapBuffers();
mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
}
#pragma mark -
@implementation ChildView
@ -3075,10 +3346,6 @@ NSEvent* gLastDragMouseDownEvent = nil;
painted = mGeckoChild->PaintWindow(region);
} else if (mGeckoChild->GetLayerManager()->GetBackendType() == LAYERS_CLIENT) {
// We only need this so that we actually get DidPaintWindow fired
if (Compositor::GetBackend() == LAYERS_BASIC) {
ClientLayerManager *manager = static_cast<ClientLayerManager*>(mGeckoChild->GetLayerManager());
manager->SetShadowTarget(targetContext);
}
painted = mGeckoChild->PaintWindow(region);
}

View File

@ -5973,6 +5973,24 @@ nsWindow::GetSurfaceForGdkDrawable(GdkDrawable* aDrawable,
}
#endif
#if defined(MOZ_WIDGET_GTK2)
TemporaryRef<gfx::DrawTarget>
nsWindow::StartRemoteDrawing()
{
gfxASurface *surf = GetThebesSurface();
if (!surf) {
return nullptr;
}
gfx::IntSize size(surf->GetSize().width, surf->GetSize().height);
if (size.width <= 0 || size.height <= 0) {
return nullptr;
}
return gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(surf, size);
}
#endif
// return the gfxASurface for rendering to this widget
gfxASurface*
#if defined(MOZ_WIDGET_GTK2)

View File

@ -195,6 +195,10 @@ public:
guint aTime,
gpointer aData);
#if defined(MOZ_WIDGET_GTK2)
mozilla::TemporaryRef<mozilla::gfx::DrawTarget> StartRemoteDrawing() MOZ_OVERRIDE;
#endif
private:
void NativeResize(int32_t aWidth,
int32_t aHeight,

View File

@ -22,6 +22,7 @@
#include "nsTArray.h"
#include "nsXULAppAPI.h"
#include "mozilla/layers/LayersTypes.h"
#include "mozilla/RefPtr.h"
// forward declarations
class nsFontMetrics;
@ -47,6 +48,9 @@ class CompositorChild;
class LayerManager;
class PLayerTransactionChild;
}
namespace gfx {
class DrawTarget;
}
}
/**
@ -92,8 +96,8 @@ typedef nsEventStatus (* EVENT_CALLBACK)(nsGUIEvent *event);
#endif
#define NS_IWIDGET_IID \
{ 0x5b9152, 0x56c8, 0x4a2d, \
{ 0x94, 0x9e, 0xec, 0xf5, 0x3, 0x83, 0x3d, 0x48 } }
{ 0xa2900e47, 0x0021, 0x441c, \
{ 0x9e, 0x94, 0xd5, 0x61, 0x5a, 0x31, 0x5d, 0x7a } }
/*
* Window shadow styles
@ -1192,6 +1196,31 @@ class nsIWidget : public nsISupports {
*/
virtual void DrawWindowOverlay(LayerManager* aManager, nsIntRect aRect) = 0;
/**
* Return a DrawTarget for the window which can be composited into.
*
* Called by BasicCompositor on the compositor thread for OMTC drawing
* before each composition.
*/
virtual mozilla::TemporaryRef<mozilla::gfx::DrawTarget> StartRemoteDrawing() = 0;
/**
* Ensure that what was painted into the DrawTarget returned from
* StartRemoteDrawing reaches the screen.
*
* Called by BasicCompositor on the compositor thread for OMTC drawing
* after each composition.
*/
virtual void EndRemoteDrawing() = 0;
/**
* Clean up any resources used by Start/EndRemoteDrawing.
*
* Called by BasicCompositor on the compositor thread for OMTC drawing
* when the compositor is destroyed.
*/
virtual void CleanupRemoteDrawing() = 0;
/**
* Called when Gecko knows which themed widgets exist in this window.
* The passed array contains an entry for every themed widget of the right

View File

@ -38,6 +38,7 @@
#include "mozilla/Attributes.h"
#include "nsContentUtils.h"
#include "gfxPlatform.h"
#include "mozilla/gfx/2D.h"
#ifdef ACCESSIBILITY
#include "nsAccessibilityService.h"
@ -1031,6 +1032,11 @@ CompositorChild* nsBaseWidget::GetRemoteRenderer()
return mCompositorChild;
}
TemporaryRef<mozilla::gfx::DrawTarget> nsBaseWidget::StartRemoteDrawing()
{
return nullptr;
}
//-------------------------------------------------------------------------
//
// Return the used device context

View File

@ -137,6 +137,9 @@ public:
virtual void PreRender(LayerManager* aManager) {}
virtual void DrawWindowUnderlay(LayerManager* aManager, nsIntRect aRect) {}
virtual void DrawWindowOverlay(LayerManager* aManager, nsIntRect aRect) {}
virtual mozilla::TemporaryRef<mozilla::gfx::DrawTarget> StartRemoteDrawing();
virtual void EndRemoteDrawing() { };
virtual void CleanupRemoteDrawing() { };
virtual void UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries) {}
virtual gfxASurface* GetThebesSurface();
NS_IMETHOD SetModal(bool aModal);