mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge mozilla-central and inbound
This commit is contained in:
commit
ef82d94fe6
@ -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>
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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.
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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\
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -8,9 +8,10 @@
|
||||
#define builtin_MapObject_h
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jsobj.h"
|
||||
|
||||
#include "vm/Runtime.h"
|
||||
|
||||
namespace js {
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
|
@ -9,6 +9,8 @@
|
||||
|
||||
#include "jsapi.h"
|
||||
|
||||
#include "vm/Runtime.h"
|
||||
|
||||
namespace js {
|
||||
namespace gc {
|
||||
|
||||
|
@ -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"
|
||||
|
||||
|
@ -8,7 +8,6 @@
|
||||
#define gc_Marking_h
|
||||
|
||||
#include "jsgc.h"
|
||||
#include "jscntxt.h"
|
||||
#include "jslock.h"
|
||||
|
||||
#include "gc/Barrier.h"
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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()
|
||||
{
|
||||
|
1688
js/src/jscntxt.h
1688
js/src/jscntxt.h
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
{
|
||||
|
@ -117,6 +117,7 @@ namespace js {
|
||||
class AutoDebugModeGC;
|
||||
class ArrayBufferObject;
|
||||
class DebugScopes;
|
||||
class WeakMapBase;
|
||||
}
|
||||
|
||||
struct JSCompartment
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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) {
|
||||
|
@ -116,6 +116,7 @@ CPP_SOURCES += [
|
||||
'RegExpObject.cpp',
|
||||
'RegExpStatics.cpp',
|
||||
'RootMarking.cpp',
|
||||
'Runtime.cpp',
|
||||
'SPSProfiler.cpp',
|
||||
'ScopeObject.cpp',
|
||||
'SelfHosting.cpp',
|
||||
|
@ -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
|
||||
|
@ -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. */
|
||||
|
@ -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
81
js/src/vm/Runtime-inl.h
Normal 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
264
js/src/vm/Runtime.cpp
Normal 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
1725
js/src/vm/Runtime.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -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()
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
#include "vm/Shape-inl.h"
|
||||
#include "vm/Runtime-inl.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
@ -60,6 +60,7 @@
|
||||
<item android:id="@+id/apps"
|
||||
android:icon="@drawable/ic_menu_apps"
|
||||
android:title="@string/apps"/>
|
||||
|
||||
</menu>
|
||||
|
||||
</item>
|
||||
|
@ -61,6 +61,7 @@
|
||||
<item android:id="@+id/apps"
|
||||
android:icon="@drawable/ic_menu_apps"
|
||||
android:title="@string/apps"/>
|
||||
|
||||
</menu>
|
||||
|
||||
</item>
|
||||
|
@ -61,6 +61,7 @@
|
||||
<item android:id="@+id/apps"
|
||||
android:icon="@drawable/ic_menu_apps"
|
||||
android:title="@string/apps"/>
|
||||
|
||||
</menu>
|
||||
|
||||
</item>
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user