зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-i to m-c
This commit is contained in:
Коммит
3b52fd5e83
|
@ -28,15 +28,6 @@
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::a11y;
|
using namespace mozilla::a11y;
|
||||||
|
|
||||||
// converts a screen-global point in the cocoa coordinate system (with origo in the bottom-left corner
|
|
||||||
// of the screen), into a top-left screen point, that gecko can use.
|
|
||||||
static inline void
|
|
||||||
ConvertCocoaToGeckoPoint(NSPoint &aInPoint, nsPoint &aOutPoint)
|
|
||||||
{
|
|
||||||
float mainScreenHeight = [(NSView*)[[NSScreen screens] objectAtIndex:0] frame].size.height;
|
|
||||||
aOutPoint.MoveTo ((nscoord)aInPoint.x, (nscoord)(mainScreenHeight - aInPoint.y));
|
|
||||||
}
|
|
||||||
|
|
||||||
// returns the passed in object if it is not ignored. if it's ignored, will return
|
// returns the passed in object if it is not ignored. if it's ignored, will return
|
||||||
// the first unignored ancestor.
|
// the first unignored ancestor.
|
||||||
static inline id
|
static inline id
|
||||||
|
@ -240,19 +231,20 @@ GetClosestInterestingAccessible(id anObject)
|
||||||
if (!mGeckoAccessible)
|
if (!mGeckoAccessible)
|
||||||
return nil;
|
return nil;
|
||||||
|
|
||||||
// Convert from cocoa's coordinate system to gecko's. According to the docs
|
// Convert the given screen-global point in the cocoa coordinate system (with
|
||||||
// the point we're given is guaranteed to be bottom-left screen coordinates.
|
// origin in the bottom-left corner of the screen) into point in the Gecko
|
||||||
nsPoint geckoPoint;
|
// coordinate system (with origin in a top-left screen point).
|
||||||
ConvertCocoaToGeckoPoint (point, geckoPoint);
|
NSScreen* mainView = [[NSScreen screens] objectAtIndex:0];
|
||||||
|
NSPoint tmpPoint = NSMakePoint(point.x,
|
||||||
|
[mainView frame].size.height - point.y);
|
||||||
|
nsIntPoint geckoPoint = nsCocoaUtils::
|
||||||
|
CocoaPointsToDevPixels(tmpPoint, nsCocoaUtils::GetBackingScaleFactor(mainView));
|
||||||
|
|
||||||
nsCOMPtr<nsIAccessible> deepestFoundChild;
|
Accessible* child = mGeckoAccessible->ChildAtPoint(geckoPoint.x, geckoPoint.y,
|
||||||
mGeckoAccessible->GetDeepestChildAtPoint((int32_t)geckoPoint.x,
|
Accessible::eDeepestChild);
|
||||||
(int32_t)geckoPoint.y,
|
|
||||||
getter_AddRefs(deepestFoundChild));
|
|
||||||
|
|
||||||
// if we found something, return its native accessible.
|
if (child) {
|
||||||
if (deepestFoundChild) {
|
mozAccessible* nativeChild = GetNativeFromGeckoAccessible(child);
|
||||||
mozAccessible *nativeChild = GetNativeFromGeckoAccessible(deepestFoundChild);
|
|
||||||
if (nativeChild)
|
if (nativeChild)
|
||||||
return GetClosestInterestingAccessible(nativeChild);
|
return GetClosestInterestingAccessible(nativeChild);
|
||||||
}
|
}
|
||||||
|
@ -379,19 +371,16 @@ GetClosestInterestingAccessible(id anObject)
|
||||||
{
|
{
|
||||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||||
|
|
||||||
int32_t x, y, width, height;
|
if (!mGeckoAccessible)
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
int32_t x = 0, y = 0, width = 0, height = 0;
|
||||||
mGeckoAccessible->GetBounds(&x, &y, &width, &height);
|
mGeckoAccessible->GetBounds(&x, &y, &width, &height);
|
||||||
NSPoint p = NSMakePoint (x, y);
|
|
||||||
|
|
||||||
// The coords we get from Gecko are top-left screen coordinates.
|
NSScreen* mainView = [[NSScreen screens] objectAtIndex:0];
|
||||||
// Cocoa wants us to return bottom-left screen coordinates.
|
CGFloat scaleFactor = nsCocoaUtils::GetBackingScaleFactor(mainView);
|
||||||
// This involves two steps:
|
NSPoint p = NSMakePoint(static_cast<CGFloat>(x) / scaleFactor,
|
||||||
// 1. Put the rect in the bottom-left coord space
|
[mainView frame].size.height - static_cast<CGFloat>(y + height) / scaleFactor);
|
||||||
// 2. Subtract the height of the rect's Y-coordinate, to make the
|
|
||||||
// the rect's origin (0, 0) be in the bottom-left corner.
|
|
||||||
|
|
||||||
float mainScreenHeight = [[[NSScreen screens] objectAtIndex:0] frame].size.height;
|
|
||||||
p.y = mainScreenHeight - p.y - height;
|
|
||||||
|
|
||||||
return [NSValue valueWithPoint:p];
|
return [NSValue valueWithPoint:p];
|
||||||
|
|
||||||
|
@ -402,9 +391,15 @@ GetClosestInterestingAccessible(id anObject)
|
||||||
{
|
{
|
||||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||||
|
|
||||||
int32_t x, y, width, height;
|
if (!mGeckoAccessible)
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
int32_t x = 0, y = 0, width = 0, height = 0;
|
||||||
mGeckoAccessible->GetBounds (&x, &y, &width, &height);
|
mGeckoAccessible->GetBounds (&x, &y, &width, &height);
|
||||||
return [NSValue valueWithSize:NSMakeSize (width, height)];
|
CGFloat scaleFactor =
|
||||||
|
nsCocoaUtils::GetBackingScaleFactor([[NSScreen screens] objectAtIndex:0]);
|
||||||
|
return [NSValue valueWithSize:NSMakeSize(static_cast<CGFloat>(width) / scaleFactor,
|
||||||
|
static_cast<CGFloat>(height) / scaleFactor)];
|
||||||
|
|
||||||
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,7 +88,7 @@ pref("mozilla.widget.force-24bpp", true);
|
||||||
pref("mozilla.widget.use-buffer-pixmap", true);
|
pref("mozilla.widget.use-buffer-pixmap", true);
|
||||||
pref("mozilla.widget.disable-native-theme", true);
|
pref("mozilla.widget.disable-native-theme", true);
|
||||||
pref("layout.reflow.synthMouseMove", false);
|
pref("layout.reflow.synthMouseMove", false);
|
||||||
pref("layers.enable-tiles", false);
|
pref("layers.enable-tiles", true);
|
||||||
/*
|
/*
|
||||||
Cross Process Mutex is not supported on Mac OS X so progressive
|
Cross Process Mutex is not supported on Mac OS X so progressive
|
||||||
paint can not be enabled for B2G on Mac OS X desktop
|
paint can not be enabled for B2G on Mac OS X desktop
|
||||||
|
|
|
@ -1226,7 +1226,7 @@ var diagnosticList = [
|
||||||
check: function(frames, symbols, meta) {
|
check: function(frames, symbols, meta) {
|
||||||
|
|
||||||
return stepContains('PaintGradient', frames, symbols)
|
return stepContains('PaintGradient', frames, symbols)
|
||||||
&& stepContains('BasicTiledLayerBuffer::PaintThebesSingleBufferDraw', frames, symbols)
|
&& stepContains('ClientTiledLayerBuffer::PaintThebesSingleBufferDraw', frames, symbols)
|
||||||
;
|
;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<nobr>
|
||||||
|
<h4 contenteditable="true">
|
||||||
|
<iframe></iframe>
|
||||||
|
<applet></applet>
|
||||||
|
<nobr>
|
|
@ -146,5 +146,6 @@ load 849601.html
|
||||||
skip-if(Android) load 851353-1.html
|
skip-if(Android) load 851353-1.html
|
||||||
load 863950.html
|
load 863950.html
|
||||||
load 864448.html
|
load 864448.html
|
||||||
|
load 930250.html
|
||||||
load 942979.html
|
load 942979.html
|
||||||
load 978646.html
|
load 978646.html
|
||||||
|
|
|
@ -1264,7 +1264,17 @@ public:
|
||||||
|
|
||||||
NS_IMETHOD Run()
|
NS_IMETHOD Run()
|
||||||
{
|
{
|
||||||
|
// It may be the case that the element was removed from the
|
||||||
|
// DOM, causing this runnable to be created, then inserted back
|
||||||
|
// into the document before the this runnable had a chance to
|
||||||
|
// tear down the binding. Only tear down the binding if the element
|
||||||
|
// is still no longer in the DOM. nsXBLService::LoadBinding tears
|
||||||
|
// down the old binding if the element is inserted back into the
|
||||||
|
// DOM and loads a different binding.
|
||||||
|
if (!mElement->IsInDoc()) {
|
||||||
mManager->RemovedFromDocumentInternal(mElement, mDoc);
|
mManager->RemovedFromDocumentInternal(mElement, mDoc);
|
||||||
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#include "mozilla/dom/TextDecoder.h"
|
#include "mozilla/dom/TextDecoder.h"
|
||||||
#include "mozilla/dom/TouchEvent.h"
|
#include "mozilla/dom/TouchEvent.h"
|
||||||
#include "mozilla/dom/ShadowRoot.h"
|
#include "mozilla/dom/ShadowRoot.h"
|
||||||
|
#include "mozilla/IMEStateManager.h"
|
||||||
#include "mozilla/InternalMutationEvent.h"
|
#include "mozilla/InternalMutationEvent.h"
|
||||||
#include "mozilla/Likely.h"
|
#include "mozilla/Likely.h"
|
||||||
#include "mozilla/MouseEvents.h"
|
#include "mozilla/MouseEvents.h"
|
||||||
|
@ -122,7 +123,6 @@
|
||||||
#include "nsILineBreaker.h"
|
#include "nsILineBreaker.h"
|
||||||
#include "nsILoadContext.h"
|
#include "nsILoadContext.h"
|
||||||
#include "nsILoadGroup.h"
|
#include "nsILoadGroup.h"
|
||||||
#include "nsIMEStateManager.h"
|
|
||||||
#include "nsIMIMEService.h"
|
#include "nsIMIMEService.h"
|
||||||
#include "nsINode.h"
|
#include "nsINode.h"
|
||||||
#include "nsINodeInfo.h"
|
#include "nsINodeInfo.h"
|
||||||
|
@ -4324,7 +4324,7 @@ nsContentUtils::DestroyAnonymousContent(nsCOMPtr<Element>* aElement)
|
||||||
void
|
void
|
||||||
nsContentUtils::NotifyInstalledMenuKeyboardListener(bool aInstalling)
|
nsContentUtils::NotifyInstalledMenuKeyboardListener(bool aInstalling)
|
||||||
{
|
{
|
||||||
nsIMEStateManager::OnInstalledMenuKeyboardListener(aInstalling);
|
IMEStateManager::OnInstalledMenuKeyboardListener(aInstalling);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool SchemeIs(nsIURI* aURI, const char* aScheme)
|
static bool SchemeIs(nsIURI* aURI, const char* aScheme)
|
||||||
|
|
|
@ -116,7 +116,6 @@ WebGLContext::WebGLContext()
|
||||||
mOptionsFrozen = false;
|
mOptionsFrozen = false;
|
||||||
|
|
||||||
mActiveTexture = 0;
|
mActiveTexture = 0;
|
||||||
mWebGLError = LOCAL_GL_NO_ERROR;
|
|
||||||
mPixelStoreFlipY = false;
|
mPixelStoreFlipY = false;
|
||||||
mPixelStorePremultiplyAlpha = false;
|
mPixelStorePremultiplyAlpha = false;
|
||||||
mPixelStoreColorspaceConversion = BROWSER_DEFAULT_WEBGL;
|
mPixelStoreColorspaceConversion = BROWSER_DEFAULT_WEBGL;
|
||||||
|
@ -1289,7 +1288,7 @@ WebGLContext::RobustnessTimerCallback(nsITimer* timer)
|
||||||
true);
|
true);
|
||||||
// Set all flags back to the state they were in before the context was
|
// Set all flags back to the state they were in before the context was
|
||||||
// lost.
|
// lost.
|
||||||
mContextLostErrorSet = false;
|
mEmitContextLostErrorOnce = true;
|
||||||
mAllowRestore = true;
|
mAllowRestore = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -244,10 +244,6 @@ public:
|
||||||
// Calls ForceClearFramebufferWithDefaultValues() for the Context's 'screen'.
|
// Calls ForceClearFramebufferWithDefaultValues() for the Context's 'screen'.
|
||||||
void ClearScreen();
|
void ClearScreen();
|
||||||
|
|
||||||
// checks for GL errors, clears any pending GL error, stores the current GL error in currentGLError (if not nullptr),
|
|
||||||
// and copies it into mWebGLError if it doesn't already have an error set
|
|
||||||
void UpdateWebGLErrorAndClearGLError(GLenum *currentGLError = nullptr);
|
|
||||||
|
|
||||||
bool MinCapabilityMode() const { return mMinCapability; }
|
bool MinCapabilityMode() const { return mMinCapability; }
|
||||||
|
|
||||||
void RobustnessTimerCallback(nsITimer* timer);
|
void RobustnessTimerCallback(nsITimer* timer);
|
||||||
|
@ -852,7 +848,12 @@ protected:
|
||||||
void DeleteWebGLObjectsArray(nsTArray<WebGLObjectType>& array);
|
void DeleteWebGLObjectsArray(nsTArray<WebGLObjectType>& array);
|
||||||
|
|
||||||
GLuint mActiveTexture;
|
GLuint mActiveTexture;
|
||||||
|
|
||||||
|
// glGetError sources:
|
||||||
|
bool mEmitContextLostErrorOnce;
|
||||||
GLenum mWebGLError;
|
GLenum mWebGLError;
|
||||||
|
GLenum mUnderlyingGLError;
|
||||||
|
GLenum GetAndFlushUnderlyingGLErrors();
|
||||||
|
|
||||||
// whether shader validation is supported
|
// whether shader validation is supported
|
||||||
bool mShaderValidation;
|
bool mShaderValidation;
|
||||||
|
@ -895,6 +896,7 @@ protected:
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// WebGL extensions (implemented in WebGLContextExtensions.cpp)
|
// WebGL extensions (implemented in WebGLContextExtensions.cpp)
|
||||||
enum WebGLExtensionID {
|
enum WebGLExtensionID {
|
||||||
|
EXT_color_buffer_half_float,
|
||||||
EXT_frag_depth,
|
EXT_frag_depth,
|
||||||
EXT_sRGB,
|
EXT_sRGB,
|
||||||
EXT_texture_filter_anisotropic,
|
EXT_texture_filter_anisotropic,
|
||||||
|
@ -905,6 +907,7 @@ protected:
|
||||||
OES_texture_half_float,
|
OES_texture_half_float,
|
||||||
OES_texture_half_float_linear,
|
OES_texture_half_float_linear,
|
||||||
OES_vertex_array_object,
|
OES_vertex_array_object,
|
||||||
|
WEBGL_color_buffer_float,
|
||||||
WEBGL_compressed_texture_atc,
|
WEBGL_compressed_texture_atc,
|
||||||
WEBGL_compressed_texture_pvrtc,
|
WEBGL_compressed_texture_pvrtc,
|
||||||
WEBGL_compressed_texture_s3tc,
|
WEBGL_compressed_texture_s3tc,
|
||||||
|
@ -933,7 +936,6 @@ protected:
|
||||||
|
|
||||||
nsTArray<GLenum> mCompressedTextureFormats;
|
nsTArray<GLenum> mCompressedTextureFormats;
|
||||||
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
// WebGL 2 specifics (implemented in WebGL2Context.cpp)
|
// WebGL 2 specifics (implemented in WebGL2Context.cpp)
|
||||||
|
|
||||||
|
|
|
@ -485,10 +485,9 @@ WebGLContext::CheckedBufferData(GLenum target,
|
||||||
|
|
||||||
bool sizeChanges = uint32_t(size) != boundBuffer->ByteLength();
|
bool sizeChanges = uint32_t(size) != boundBuffer->ByteLength();
|
||||||
if (sizeChanges) {
|
if (sizeChanges) {
|
||||||
UpdateWebGLErrorAndClearGLError();
|
GetAndFlushUnderlyingGLErrors();
|
||||||
gl->fBufferData(target, size, data, usage);
|
gl->fBufferData(target, size, data, usage);
|
||||||
GLenum error = LOCAL_GL_NO_ERROR;
|
GLenum error = GetAndFlushUnderlyingGLErrors();
|
||||||
UpdateWebGLErrorAndClearGLError(&error);
|
|
||||||
return error;
|
return error;
|
||||||
} else {
|
} else {
|
||||||
gl->fBufferData(target, size, data, usage);
|
gl->fBufferData(target, size, data, usage);
|
||||||
|
|
|
@ -17,6 +17,7 @@ using namespace mozilla::gl;
|
||||||
|
|
||||||
// must match WebGLContext::WebGLExtensionID
|
// must match WebGLContext::WebGLExtensionID
|
||||||
static const char *sExtensionNames[] = {
|
static const char *sExtensionNames[] = {
|
||||||
|
"EXT_color_buffer_half_float",
|
||||||
"EXT_frag_depth",
|
"EXT_frag_depth",
|
||||||
"EXT_sRGB",
|
"EXT_sRGB",
|
||||||
"EXT_texture_filter_anisotropic",
|
"EXT_texture_filter_anisotropic",
|
||||||
|
@ -27,6 +28,7 @@ static const char *sExtensionNames[] = {
|
||||||
"OES_texture_half_float",
|
"OES_texture_half_float",
|
||||||
"OES_texture_half_float_linear",
|
"OES_texture_half_float_linear",
|
||||||
"OES_vertex_array_object",
|
"OES_vertex_array_object",
|
||||||
|
"WEBGL_color_buffer_float",
|
||||||
"WEBGL_compressed_texture_atc",
|
"WEBGL_compressed_texture_atc",
|
||||||
"WEBGL_compressed_texture_pvrtc",
|
"WEBGL_compressed_texture_pvrtc",
|
||||||
"WEBGL_compressed_texture_s3tc",
|
"WEBGL_compressed_texture_s3tc",
|
||||||
|
@ -108,6 +110,10 @@ bool WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const
|
||||||
gl->IsSupported(GLFeature::texture_half_float);
|
gl->IsSupported(GLFeature::texture_half_float);
|
||||||
case OES_texture_half_float_linear:
|
case OES_texture_half_float_linear:
|
||||||
return gl->IsSupported(GLFeature::texture_half_float_linear);
|
return gl->IsSupported(GLFeature::texture_half_float_linear);
|
||||||
|
case WEBGL_color_buffer_float:
|
||||||
|
return WebGLExtensionColorBufferFloat::IsSupported(this);
|
||||||
|
case EXT_color_buffer_half_float:
|
||||||
|
return WebGLExtensionColorBufferHalfFloat::IsSupported(this);
|
||||||
case OES_vertex_array_object:
|
case OES_vertex_array_object:
|
||||||
return WebGLExtensionVertexArray::IsSupported(this);
|
return WebGLExtensionVertexArray::IsSupported(this);
|
||||||
case EXT_texture_filter_anisotropic:
|
case EXT_texture_filter_anisotropic:
|
||||||
|
@ -286,6 +292,12 @@ WebGLContext::EnableExtension(WebGLExtensionID ext)
|
||||||
case OES_texture_half_float_linear:
|
case OES_texture_half_float_linear:
|
||||||
obj = new WebGLExtensionTextureHalfFloatLinear(this);
|
obj = new WebGLExtensionTextureHalfFloatLinear(this);
|
||||||
break;
|
break;
|
||||||
|
case WEBGL_color_buffer_float:
|
||||||
|
obj = new WebGLExtensionColorBufferFloat(this);
|
||||||
|
break;
|
||||||
|
case EXT_color_buffer_half_float:
|
||||||
|
obj = new WebGLExtensionColorBufferHalfFloat(this);
|
||||||
|
break;
|
||||||
case WEBGL_draw_buffers:
|
case WEBGL_draw_buffers:
|
||||||
obj = new WebGLExtensionDrawBuffers(this);
|
obj = new WebGLExtensionDrawBuffers(this);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -538,13 +538,12 @@ WebGLContext::CopyTexImage2D(GLenum target,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sizeMayChange)
|
if (sizeMayChange)
|
||||||
UpdateWebGLErrorAndClearGLError();
|
GetAndFlushUnderlyingGLErrors();
|
||||||
|
|
||||||
CopyTexSubImage2D_base(target, level, internalformat, 0, 0, x, y, width, height, false);
|
CopyTexSubImage2D_base(target, level, internalformat, 0, 0, x, y, width, height, false);
|
||||||
|
|
||||||
if (sizeMayChange) {
|
if (sizeMayChange) {
|
||||||
GLenum error = LOCAL_GL_NO_ERROR;
|
GLenum error = GetAndFlushUnderlyingGLErrors();
|
||||||
UpdateWebGLErrorAndClearGLError(&error);
|
|
||||||
if (error) {
|
if (error) {
|
||||||
GenerateWarning("copyTexImage2D generated error %s", ErrorName(error));
|
GenerateWarning("copyTexImage2D generated error %s", ErrorName(error));
|
||||||
return;
|
return;
|
||||||
|
@ -902,8 +901,7 @@ WebGLContext::DoFakeVertexAttrib0(GLuint vertexCount)
|
||||||
|
|
||||||
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mFakeVertexAttrib0BufferObject);
|
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mFakeVertexAttrib0BufferObject);
|
||||||
|
|
||||||
GLenum error = LOCAL_GL_NO_ERROR;
|
GetAndFlushUnderlyingGLErrors();
|
||||||
UpdateWebGLErrorAndClearGLError();
|
|
||||||
|
|
||||||
if (mFakeVertexAttrib0BufferStatus == WebGLVertexAttrib0Status::EmulatedInitializedArray) {
|
if (mFakeVertexAttrib0BufferStatus == WebGLVertexAttrib0Status::EmulatedInitializedArray) {
|
||||||
nsAutoArrayPtr<GLfloat> array(new GLfloat[4 * vertexCount]);
|
nsAutoArrayPtr<GLfloat> array(new GLfloat[4 * vertexCount]);
|
||||||
|
@ -917,7 +915,7 @@ WebGLContext::DoFakeVertexAttrib0(GLuint vertexCount)
|
||||||
} else {
|
} else {
|
||||||
gl->fBufferData(LOCAL_GL_ARRAY_BUFFER, dataSize, nullptr, LOCAL_GL_DYNAMIC_DRAW);
|
gl->fBufferData(LOCAL_GL_ARRAY_BUFFER, dataSize, nullptr, LOCAL_GL_DYNAMIC_DRAW);
|
||||||
}
|
}
|
||||||
UpdateWebGLErrorAndClearGLError(&error);
|
GLenum error = GetAndFlushUnderlyingGLErrors();
|
||||||
|
|
||||||
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mBoundArrayBuffer ? mBoundArrayBuffer->GLName() : 0);
|
gl->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, mBoundArrayBuffer ? mBoundArrayBuffer->GLName() : 0);
|
||||||
|
|
||||||
|
@ -1391,8 +1389,47 @@ WebGLContext::GetFramebufferAttachmentParameter(JSContext* cx,
|
||||||
return JS::NumberValue(uint32_t(LOCAL_GL_RENDERBUFFER));
|
return JS::NumberValue(uint32_t(LOCAL_GL_RENDERBUFFER));
|
||||||
|
|
||||||
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
|
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
|
||||||
{
|
|
||||||
return WebGLObjectAsJSValue(cx, fba.Renderbuffer(), rv);
|
return WebGLObjectAsJSValue(cx, fba.Renderbuffer(), rv);
|
||||||
|
|
||||||
|
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: {
|
||||||
|
if (!IsExtensionEnabled(EXT_color_buffer_half_float) &&
|
||||||
|
!IsExtensionEnabled(WEBGL_color_buffer_float))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attachment == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
|
||||||
|
ErrorInvalidOperation("getFramebufferAttachmentParameter: Cannot get component"
|
||||||
|
" type of a depth-stencil attachment.");
|
||||||
|
return JS::NullValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fba.IsComplete())
|
||||||
|
return JS::NumberValue(uint32_t(LOCAL_GL_NONE));
|
||||||
|
|
||||||
|
uint32_t ret = LOCAL_GL_NONE;
|
||||||
|
switch (fba.Renderbuffer()->InternalFormat()) {
|
||||||
|
case LOCAL_GL_RGBA4:
|
||||||
|
case LOCAL_GL_RGB5_A1:
|
||||||
|
case LOCAL_GL_RGB565:
|
||||||
|
case LOCAL_GL_SRGB8_ALPHA8:
|
||||||
|
ret = LOCAL_GL_UNSIGNED_NORMALIZED;
|
||||||
|
break;
|
||||||
|
case LOCAL_GL_RGB16F:
|
||||||
|
case LOCAL_GL_RGBA16F:
|
||||||
|
case LOCAL_GL_RGB32F:
|
||||||
|
case LOCAL_GL_RGBA32F:
|
||||||
|
ret = LOCAL_GL_FLOAT;
|
||||||
|
break;
|
||||||
|
case LOCAL_GL_DEPTH_COMPONENT16:
|
||||||
|
case LOCAL_GL_STENCIL_INDEX8:
|
||||||
|
ret = LOCAL_GL_UNSIGNED_INT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
MOZ_ASSERT(false, "Unhandled RB component type.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return JS::NumberValue(uint32_t(ret));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1415,20 +1452,58 @@ WebGLContext::GetFramebufferAttachmentParameter(JSContext* cx,
|
||||||
return JS::NumberValue(uint32_t(LOCAL_GL_TEXTURE));
|
return JS::NumberValue(uint32_t(LOCAL_GL_TEXTURE));
|
||||||
|
|
||||||
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
|
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
|
||||||
{
|
|
||||||
return WebGLObjectAsJSValue(cx, fba.Texture(), rv);
|
return WebGLObjectAsJSValue(cx, fba.Texture(), rv);
|
||||||
}
|
|
||||||
|
|
||||||
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
|
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
|
||||||
return JS::Int32Value(fba.TexImageLevel());
|
return JS::Int32Value(fba.TexImageLevel());
|
||||||
|
|
||||||
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
|
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: {
|
||||||
{
|
|
||||||
GLenum face = fba.TexImageTarget();
|
GLenum face = fba.TexImageTarget();
|
||||||
if (face == LOCAL_GL_TEXTURE_2D)
|
if (face == LOCAL_GL_TEXTURE_2D)
|
||||||
face = 0;
|
face = 0;
|
||||||
return JS::Int32Value(face);
|
return JS::Int32Value(face);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: {
|
||||||
|
if (!IsExtensionEnabled(EXT_color_buffer_half_float) &&
|
||||||
|
!IsExtensionEnabled(WEBGL_color_buffer_float))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attachment == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
|
||||||
|
ErrorInvalidOperation("getFramebufferAttachmentParameter: cannot component"
|
||||||
|
" type of depth-stencil attachments.");
|
||||||
|
return JS::NullValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fba.IsComplete())
|
||||||
|
return JS::NumberValue(uint32_t(LOCAL_GL_NONE));
|
||||||
|
|
||||||
|
uint32_t ret = LOCAL_GL_NONE;
|
||||||
|
GLenum type = fba.Texture()->ImageInfoAt(fba.TexImageTarget(),
|
||||||
|
fba.TexImageLevel()).Type();
|
||||||
|
switch (type) {
|
||||||
|
case LOCAL_GL_UNSIGNED_BYTE:
|
||||||
|
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
|
||||||
|
case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
|
||||||
|
case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
|
||||||
|
ret = LOCAL_GL_UNSIGNED_NORMALIZED;
|
||||||
|
break;
|
||||||
|
case LOCAL_GL_FLOAT:
|
||||||
|
case LOCAL_GL_HALF_FLOAT_OES:
|
||||||
|
ret = LOCAL_GL_FLOAT;
|
||||||
|
break;
|
||||||
|
case LOCAL_GL_UNSIGNED_SHORT:
|
||||||
|
case LOCAL_GL_UNSIGNED_INT:
|
||||||
|
ret = LOCAL_GL_UNSIGNED_INT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
MOZ_ASSERT(false, "Unhandled RB component type.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return JS::NumberValue(uint32_t(ret));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ErrorInvalidEnumInfo("getFramebufferAttachmentParameter: pname", pname);
|
ErrorInvalidEnumInfo("getFramebufferAttachmentParameter: pname", pname);
|
||||||
|
@ -1499,19 +1574,53 @@ WebGLContext::CreateTexture()
|
||||||
return globj.forget();
|
return globj.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GLenum
|
||||||
|
GetAndClearError(GLenum* errorVar)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(errorVar);
|
||||||
|
GLenum ret = *errorVar;
|
||||||
|
*errorVar = LOCAL_GL_NO_ERROR;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
GLenum
|
GLenum
|
||||||
WebGLContext::GetError()
|
WebGLContext::GetError()
|
||||||
{
|
{
|
||||||
if (mContextStatus == ContextNotLost) {
|
/* WebGL 1.0: Section 5.14.3: Setting and getting state:
|
||||||
MakeContextCurrent();
|
* If the context's webgl context lost flag is set, returns
|
||||||
UpdateWebGLErrorAndClearGLError();
|
* CONTEXT_LOST_WEBGL the first time this method is called.
|
||||||
} else if (!mContextLostErrorSet) {
|
* Afterward, returns NO_ERROR until the context has been
|
||||||
mWebGLError = LOCAL_GL_CONTEXT_LOST;
|
* restored.
|
||||||
mContextLostErrorSet = true;
|
*
|
||||||
|
* WEBGL_lose_context:
|
||||||
|
* [When this extension is enabled: ] loseContext and
|
||||||
|
* restoreContext are allowed to generate INVALID_OPERATION errors
|
||||||
|
* even when the context is lost.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (IsContextLost()) {
|
||||||
|
if (mEmitContextLostErrorOnce) {
|
||||||
|
mEmitContextLostErrorOnce = false;
|
||||||
|
return LOCAL_GL_CONTEXT_LOST;
|
||||||
|
}
|
||||||
|
// Don't return yet, since WEBGL_lose_contexts contradicts the
|
||||||
|
// original spec, and allows error generation while lost.
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum err = mWebGLError;
|
GLenum err = GetAndClearError(&mWebGLError);
|
||||||
mWebGLError = LOCAL_GL_NO_ERROR;
|
if (err != LOCAL_GL_NO_ERROR)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (IsContextLost())
|
||||||
|
return LOCAL_GL_NO_ERROR;
|
||||||
|
|
||||||
|
// Either no WebGL-side error, or it's already been cleared.
|
||||||
|
// UnderlyingGL-side errors, now.
|
||||||
|
|
||||||
|
MakeContextCurrent();
|
||||||
|
GetAndFlushUnderlyingGLErrors();
|
||||||
|
|
||||||
|
err = GetAndClearError(&mUnderlyingGLError);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2215,9 +2324,8 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width,
|
||||||
GLenum type, const Nullable<ArrayBufferView> &pixels,
|
GLenum type, const Nullable<ArrayBufferView> &pixels,
|
||||||
ErrorResult& rv)
|
ErrorResult& rv)
|
||||||
{
|
{
|
||||||
if (IsContextLost()) {
|
if (IsContextLost())
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if (mCanvasElement->IsWriteOnly() && !nsContentUtils::IsCallerChrome()) {
|
if (mCanvasElement->IsWriteOnly() && !nsContentUtils::IsCallerChrome()) {
|
||||||
GenerateWarning("readPixels: Not allowed");
|
GenerateWarning("readPixels: Not allowed");
|
||||||
|
@ -2255,20 +2363,34 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width,
|
||||||
int requiredDataType = 0;
|
int requiredDataType = 0;
|
||||||
|
|
||||||
// Check the type param
|
// Check the type param
|
||||||
|
bool isReadTypeValid = false;
|
||||||
|
bool isReadTypeFloat = false;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case LOCAL_GL_UNSIGNED_BYTE:
|
case LOCAL_GL_UNSIGNED_BYTE:
|
||||||
|
isReadTypeValid = true;
|
||||||
bytesPerPixel = 1*channels;
|
bytesPerPixel = 1*channels;
|
||||||
requiredDataType = js::ArrayBufferView::TYPE_UINT8;
|
requiredDataType = js::ArrayBufferView::TYPE_UINT8;
|
||||||
break;
|
break;
|
||||||
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
|
case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
|
||||||
case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
|
case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
|
||||||
case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
|
case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
|
||||||
|
isReadTypeValid = true;
|
||||||
bytesPerPixel = 2;
|
bytesPerPixel = 2;
|
||||||
requiredDataType = js::ArrayBufferView::TYPE_UINT16;
|
requiredDataType = js::ArrayBufferView::TYPE_UINT16;
|
||||||
break;
|
break;
|
||||||
default:
|
case LOCAL_GL_FLOAT:
|
||||||
return ErrorInvalidEnum("readPixels: Bad type");
|
if (IsExtensionEnabled(WEBGL_color_buffer_float) ||
|
||||||
|
IsExtensionEnabled(EXT_color_buffer_half_float))
|
||||||
|
{
|
||||||
|
isReadTypeValid = true;
|
||||||
|
isReadTypeFloat = true;
|
||||||
|
bytesPerPixel = 4*channels;
|
||||||
|
requiredDataType = js::ArrayBufferView::TYPE_FLOAT32;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!isReadTypeValid)
|
||||||
|
return ErrorInvalidEnum("readPixels: Bad type", type);
|
||||||
|
|
||||||
int dataType = JS_GetArrayBufferViewType(pixels.Value().Obj());
|
int dataType = JS_GetArrayBufferViewType(pixels.Value().Obj());
|
||||||
|
|
||||||
|
@ -2298,12 +2420,25 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width,
|
||||||
return rv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
return rv.Throw(NS_ERROR_OUT_OF_MEMORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isSourceTypeFloat = false;
|
||||||
|
if (mBoundFramebuffer &&
|
||||||
|
mBoundFramebuffer->ColorAttachmentCount() &&
|
||||||
|
mBoundFramebuffer->ColorAttachment(0).IsDefined())
|
||||||
|
{
|
||||||
|
isSourceTypeFloat = mBoundFramebuffer->ColorAttachment(0).IsReadableFloat();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isReadTypeFloat != isSourceTypeFloat)
|
||||||
|
return ErrorInvalidOperation("readPixels: Invalid type floatness");
|
||||||
|
|
||||||
// Check the format and type params to assure they are an acceptable pair (as per spec)
|
// Check the format and type params to assure they are an acceptable pair (as per spec)
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case LOCAL_GL_RGBA: {
|
case LOCAL_GL_RGBA: {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case LOCAL_GL_UNSIGNED_BYTE:
|
case LOCAL_GL_UNSIGNED_BYTE:
|
||||||
break;
|
break;
|
||||||
|
case LOCAL_GL_FLOAT:
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return ErrorInvalidOperation("readPixels: Invalid format/type pair");
|
return ErrorInvalidOperation("readPixels: Invalid format/type pair");
|
||||||
}
|
}
|
||||||
|
@ -2431,6 +2566,20 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width,
|
||||||
rowp += 4;
|
rowp += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
row += checked_alignedRowSize.value();
|
||||||
|
}
|
||||||
|
} else if (format == LOCAL_GL_RGBA && type == LOCAL_GL_FLOAT) {
|
||||||
|
float* row = static_cast<float*>(data);
|
||||||
|
|
||||||
|
for (GLint j = 0; j < height; ++j) {
|
||||||
|
float* pAlpha = row + 3;
|
||||||
|
float* pAlphaEnd = pAlpha + 4*width;
|
||||||
|
|
||||||
|
while (pAlpha != pAlphaEnd) {
|
||||||
|
*pAlpha = 1.0f;
|
||||||
|
pAlpha += 4;
|
||||||
|
}
|
||||||
|
|
||||||
row += checked_alignedRowSize.value();
|
row += checked_alignedRowSize.value();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -2486,6 +2635,22 @@ WebGLContext::RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei
|
||||||
break;
|
break;
|
||||||
case LOCAL_GL_SRGB8_ALPHA8_EXT:
|
case LOCAL_GL_SRGB8_ALPHA8_EXT:
|
||||||
break;
|
break;
|
||||||
|
case LOCAL_GL_RGB16F:
|
||||||
|
case LOCAL_GL_RGBA16F: {
|
||||||
|
bool hasExtensions = IsExtensionEnabled(OES_texture_half_float) &&
|
||||||
|
IsExtensionEnabled(EXT_color_buffer_half_float);
|
||||||
|
if (!hasExtensions)
|
||||||
|
return ErrorInvalidEnumInfo("renderbufferStorage: internalformat", target);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case LOCAL_GL_RGB32F:
|
||||||
|
case LOCAL_GL_RGBA32F: {
|
||||||
|
bool hasExtensions = IsExtensionEnabled(OES_texture_float) &&
|
||||||
|
IsExtensionEnabled(WEBGL_color_buffer_float);
|
||||||
|
if (!hasExtensions)
|
||||||
|
return ErrorInvalidEnumInfo("renderbufferStorage: internalformat", target);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return ErrorInvalidEnumInfo("renderbufferStorage: internalformat", internalformat);
|
return ErrorInvalidEnumInfo("renderbufferStorage: internalformat", internalformat);
|
||||||
}
|
}
|
||||||
|
@ -2496,10 +2661,9 @@ WebGLContext::RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei
|
||||||
height != mBoundRenderbuffer->Height() ||
|
height != mBoundRenderbuffer->Height() ||
|
||||||
internalformat != mBoundRenderbuffer->InternalFormat();
|
internalformat != mBoundRenderbuffer->InternalFormat();
|
||||||
if (sizeChanges) {
|
if (sizeChanges) {
|
||||||
UpdateWebGLErrorAndClearGLError();
|
GetAndFlushUnderlyingGLErrors();
|
||||||
mBoundRenderbuffer->RenderbufferStorage(internalformatForGL, width, height);
|
mBoundRenderbuffer->RenderbufferStorage(internalformatForGL, width, height);
|
||||||
GLenum error = LOCAL_GL_NO_ERROR;
|
GLenum error = GetAndFlushUnderlyingGLErrors();
|
||||||
UpdateWebGLErrorAndClearGLError(&error);
|
|
||||||
if (error) {
|
if (error) {
|
||||||
GenerateWarning("renderbufferStorage generated error %s", ErrorName(error));
|
GenerateWarning("renderbufferStorage generated error %s", ErrorName(error));
|
||||||
return;
|
return;
|
||||||
|
@ -3632,12 +3796,11 @@ GLenum WebGLContext::CheckedTexImage2D(GLenum target,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sizeMayChange) {
|
if (sizeMayChange) {
|
||||||
UpdateWebGLErrorAndClearGLError();
|
GetAndFlushUnderlyingGLErrors();
|
||||||
|
|
||||||
gl->fTexImage2D(target, level, internalFormat, width, height, border, format, realType, data);
|
gl->fTexImage2D(target, level, internalFormat, width, height, border, format, realType, data);
|
||||||
|
|
||||||
GLenum error = LOCAL_GL_NO_ERROR;
|
GLenum error = GetAndFlushUnderlyingGLErrors();
|
||||||
UpdateWebGLErrorAndClearGLError(&error);
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3881,8 +4044,13 @@ WebGLContext::TexSubImage2D_base(GLenum target, GLint level,
|
||||||
|
|
||||||
// convert type for half float if not on GLES2
|
// convert type for half float if not on GLES2
|
||||||
GLenum realType = type;
|
GLenum realType = type;
|
||||||
if (realType == LOCAL_GL_HALF_FLOAT_OES && !gl->IsGLES2())
|
if (realType == LOCAL_GL_HALF_FLOAT_OES) {
|
||||||
|
if (gl->IsSupported(gl::GLFeature::texture_half_float)) {
|
||||||
realType = LOCAL_GL_HALF_FLOAT;
|
realType = LOCAL_GL_HALF_FLOAT;
|
||||||
|
} else {
|
||||||
|
MOZ_ASSERT(gl->IsExtensionSupported(gl::GLContext::OES_texture_half_float));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (actualSrcFormat == dstFormat &&
|
if (actualSrcFormat == dstFormat &&
|
||||||
srcPremultiplied == mPixelStorePremultiplyAlpha &&
|
srcPremultiplied == mPixelStorePremultiplyAlpha &&
|
||||||
|
|
|
@ -106,15 +106,12 @@ WebGLContext::GetImageSize(GLsizei height,
|
||||||
void
|
void
|
||||||
WebGLContext::SynthesizeGLError(GLenum err)
|
WebGLContext::SynthesizeGLError(GLenum err)
|
||||||
{
|
{
|
||||||
// If there is already a pending error, don't overwrite it;
|
/* ES2 section 2.5 "GL Errors" states that implementations can have
|
||||||
// but if there isn't, then we need to check for a gl error
|
* multiple 'flags', as errors might be caught in different parts of
|
||||||
// that may have occurred before this one and use that code
|
* a distributed implementation.
|
||||||
// instead.
|
* We're signing up as a distributed implementation here, with
|
||||||
|
* separate flags for WebGL and the underlying GLContext.
|
||||||
MakeContextCurrent();
|
*/
|
||||||
|
|
||||||
UpdateWebGLErrorAndClearGLError();
|
|
||||||
|
|
||||||
if (!mWebGLError)
|
if (!mWebGLError)
|
||||||
mWebGLError = err;
|
mWebGLError = err;
|
||||||
}
|
}
|
||||||
|
@ -234,14 +231,16 @@ WebGLContext::IsTextureFormatCompressed(GLenum format)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
GLenum
|
||||||
WebGLContext::UpdateWebGLErrorAndClearGLError(GLenum *currentGLError)
|
WebGLContext::GetAndFlushUnderlyingGLErrors()
|
||||||
{
|
{
|
||||||
// get and clear GL error in ALL cases
|
// Get and clear GL error in ALL cases.
|
||||||
GLenum error = gl->GetAndClearError();
|
GLenum error = gl->GetAndClearError();
|
||||||
if (currentGLError)
|
|
||||||
*currentGLError = error;
|
// Only store in mUnderlyingGLError if is hasn't already recorded an
|
||||||
// only store in mWebGLError if is hasn't already recorded an error
|
// error.
|
||||||
if (!mWebGLError)
|
if (!mUnderlyingGLError)
|
||||||
mWebGLError = error;
|
mUnderlyingGLError = error;
|
||||||
|
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1586,7 +1586,9 @@ WebGLContext::InitAndValidateGL()
|
||||||
}
|
}
|
||||||
|
|
||||||
mActiveTexture = 0;
|
mActiveTexture = 0;
|
||||||
|
mEmitContextLostErrorOnce = true;
|
||||||
mWebGLError = LOCAL_GL_NO_ERROR;
|
mWebGLError = LOCAL_GL_NO_ERROR;
|
||||||
|
mUnderlyingGLError = LOCAL_GL_NO_ERROR;
|
||||||
|
|
||||||
mBound2DTextures.Clear();
|
mBound2DTextures.Clear();
|
||||||
mBoundCubeMapTextures.Clear();
|
mBoundCubeMapTextures.Clear();
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
/* 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 "WebGLExtensions.h"
|
||||||
|
|
||||||
|
#include "GLContext.h"
|
||||||
|
#include "mozilla/dom/WebGLRenderingContextBinding.h"
|
||||||
|
#include "WebGLContext.h"
|
||||||
|
|
||||||
|
using namespace mozilla;
|
||||||
|
|
||||||
|
WebGLExtensionColorBufferFloat::WebGLExtensionColorBufferFloat(WebGLContext* context)
|
||||||
|
: WebGLExtensionBase(context)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsSupported(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
WebGLExtensionColorBufferFloat::~WebGLExtensionColorBufferFloat()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
WebGLExtensionColorBufferFloat::IsSupported(const WebGLContext* context)
|
||||||
|
{
|
||||||
|
return context->GL()->IsSupported(gl::GLFeature::renderbuffer_color_float) &&
|
||||||
|
context->GL()->IsSupported(gl::GLFeature::frag_color_float);
|
||||||
|
}
|
||||||
|
|
||||||
|
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionColorBufferFloat)
|
|
@ -0,0 +1,30 @@
|
||||||
|
/* 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 "WebGLExtensions.h"
|
||||||
|
|
||||||
|
#include "GLContext.h"
|
||||||
|
#include "mozilla/dom/WebGLRenderingContextBinding.h"
|
||||||
|
#include "WebGLContext.h"
|
||||||
|
|
||||||
|
using namespace mozilla;
|
||||||
|
|
||||||
|
WebGLExtensionColorBufferHalfFloat::WebGLExtensionColorBufferHalfFloat(WebGLContext* context)
|
||||||
|
: WebGLExtensionBase(context)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsSupported(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
WebGLExtensionColorBufferHalfFloat::~WebGLExtensionColorBufferHalfFloat()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
WebGLExtensionColorBufferHalfFloat::IsSupported(const WebGLContext* context)
|
||||||
|
{
|
||||||
|
return context->GL()->IsSupported(gl::GLFeature::renderbuffer_color_half_float) &&
|
||||||
|
context->GL()->IsSupported(gl::GLFeature::frag_color_float);
|
||||||
|
}
|
||||||
|
|
||||||
|
IMPL_WEBGL_EXTENSION_GOOP(WebGLExtensionColorBufferHalfFloat)
|
|
@ -6,9 +6,17 @@
|
||||||
#ifndef WEBGLEXTENSIONS_H_
|
#ifndef WEBGLEXTENSIONS_H_
|
||||||
#define WEBGLEXTENSIONS_H_
|
#define WEBGLEXTENSIONS_H_
|
||||||
|
|
||||||
|
#include "jsapi.h"
|
||||||
|
#include "mozilla/Attributes.h"
|
||||||
|
#include "nsWrapperCache.h"
|
||||||
|
#include "WebGLObjectModel.h"
|
||||||
|
#include "WebGLTypes.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
class WebGLContext;
|
class WebGLContext;
|
||||||
|
class WebGLShader;
|
||||||
|
class WebGLVertexArray;
|
||||||
|
|
||||||
class WebGLExtensionBase
|
class WebGLExtensionBase
|
||||||
: public nsWrapperCache
|
: public nsWrapperCache
|
||||||
|
@ -205,6 +213,30 @@ public:
|
||||||
DECL_WEBGL_EXTENSION_GOOP
|
DECL_WEBGL_EXTENSION_GOOP
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class WebGLExtensionColorBufferFloat
|
||||||
|
: public WebGLExtensionBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WebGLExtensionColorBufferFloat(WebGLContext*);
|
||||||
|
virtual ~WebGLExtensionColorBufferFloat();
|
||||||
|
|
||||||
|
static bool IsSupported(const WebGLContext*);
|
||||||
|
|
||||||
|
DECL_WEBGL_EXTENSION_GOOP
|
||||||
|
};
|
||||||
|
|
||||||
|
class WebGLExtensionColorBufferHalfFloat
|
||||||
|
: public WebGLExtensionBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
WebGLExtensionColorBufferHalfFloat(WebGLContext*);
|
||||||
|
virtual ~WebGLExtensionColorBufferHalfFloat();
|
||||||
|
|
||||||
|
static bool IsSupported(const WebGLContext*);
|
||||||
|
|
||||||
|
DECL_WEBGL_EXTENSION_GOOP
|
||||||
|
};
|
||||||
|
|
||||||
class WebGLExtensionDrawBuffers
|
class WebGLExtensionDrawBuffers
|
||||||
: public WebGLExtensionBase
|
: public WebGLExtensionBase
|
||||||
{
|
{
|
||||||
|
|
|
@ -60,6 +60,35 @@ WebGLFramebuffer::Attachment::HasAlpha() const
|
||||||
return FormatHasAlpha(format);
|
return FormatHasAlpha(format);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
WebGLFramebuffer::Attachment::IsReadableFloat() const
|
||||||
|
{
|
||||||
|
if (Texture() && Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel)) {
|
||||||
|
GLenum type = Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel).Type();
|
||||||
|
switch (type) {
|
||||||
|
case LOCAL_GL_FLOAT:
|
||||||
|
case LOCAL_GL_HALF_FLOAT_OES:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Renderbuffer()) {
|
||||||
|
GLenum format = Renderbuffer()->InternalFormat();
|
||||||
|
switch (format) {
|
||||||
|
case LOCAL_GL_RGB16F:
|
||||||
|
case LOCAL_GL_RGBA16F:
|
||||||
|
case LOCAL_GL_RGB32F:
|
||||||
|
case LOCAL_GL_RGBA32F:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(false, "Should not get here.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
WebGLFramebuffer::Attachment::SetTexImage(WebGLTexture* tex, GLenum target, GLint level)
|
WebGLFramebuffer::Attachment::SetTexImage(WebGLTexture* tex, GLenum target, GLint level)
|
||||||
{
|
{
|
||||||
|
|
|
@ -53,6 +53,7 @@ public:
|
||||||
bool IsDeleteRequested() const;
|
bool IsDeleteRequested() const;
|
||||||
|
|
||||||
bool HasAlpha() const;
|
bool HasAlpha() const;
|
||||||
|
bool IsReadableFloat() const;
|
||||||
|
|
||||||
void SetTexImage(WebGLTexture* tex, GLenum target, GLint level);
|
void SetTexImage(WebGLTexture* tex, GLenum target, GLint level);
|
||||||
void SetRenderbuffer(WebGLRenderbuffer* rb) {
|
void SetRenderbuffer(WebGLRenderbuffer* rb) {
|
||||||
|
|
|
@ -113,6 +113,18 @@ WebGLRenderbuffer::MemoryUsage() const {
|
||||||
case LOCAL_GL_DEPTH_COMPONENT32:
|
case LOCAL_GL_DEPTH_COMPONENT32:
|
||||||
primarySize = 4*pixels;
|
primarySize = 4*pixels;
|
||||||
break;
|
break;
|
||||||
|
case LOCAL_GL_RGB16F:
|
||||||
|
primarySize = 2*3*pixels;
|
||||||
|
break;
|
||||||
|
case LOCAL_GL_RGBA16F:
|
||||||
|
primarySize = 2*4*pixels;
|
||||||
|
break;
|
||||||
|
case LOCAL_GL_RGB32F:
|
||||||
|
primarySize = 4*3*pixels;
|
||||||
|
break;
|
||||||
|
case LOCAL_GL_RGBA32F:
|
||||||
|
primarySize = 4*4*pixels;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
MOZ_ASSERT(false, "Unknown `primaryFormat`.");
|
MOZ_ASSERT(false, "Unknown `primaryFormat`.");
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -49,8 +49,8 @@ int64_t
|
||||||
WebGLTexture::ImageInfo::MemoryUsage() const {
|
WebGLTexture::ImageInfo::MemoryUsage() const {
|
||||||
if (mImageDataStatus == WebGLImageDataStatus::NoImageData)
|
if (mImageDataStatus == WebGLImageDataStatus::NoImageData)
|
||||||
return 0;
|
return 0;
|
||||||
int64_t texelSizeInBits = WebGLContext::GetBitsPerTexel(mInternalFormat, mType);
|
int64_t bitsPerTexel = WebGLContext::GetBitsPerTexel(mInternalFormat, mType);
|
||||||
return int64_t(mWidth) * int64_t(mHeight) * texelSizeInBits / 8;
|
return int64_t(mWidth) * int64_t(mHeight) * bitsPerTexel/8;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t
|
int64_t
|
||||||
|
@ -451,13 +451,12 @@ WebGLTexture::DoDeferredImageInitialization(GLenum imageTarget, GLint level)
|
||||||
void *zeros = calloc(1, checked_byteLength.value());
|
void *zeros = calloc(1, checked_byteLength.value());
|
||||||
|
|
||||||
GLenum format = WebGLTexelConversions::GLFormatForTexelFormat(texelformat);
|
GLenum format = WebGLTexelConversions::GLFormatForTexelFormat(texelformat);
|
||||||
mContext->UpdateWebGLErrorAndClearGLError();
|
mContext->GetAndFlushUnderlyingGLErrors();
|
||||||
mContext->gl->fTexImage2D(imageTarget, level, imageInfo.mInternalFormat,
|
mContext->gl->fTexImage2D(imageTarget, level, imageInfo.mInternalFormat,
|
||||||
imageInfo.mWidth, imageInfo.mHeight,
|
imageInfo.mWidth, imageInfo.mHeight,
|
||||||
0, format, imageInfo.mType,
|
0, format, imageInfo.mType,
|
||||||
zeros);
|
zeros);
|
||||||
GLenum error = LOCAL_GL_NO_ERROR;
|
GLenum error = mContext->GetAndFlushUnderlyingGLErrors();
|
||||||
mContext->UpdateWebGLErrorAndClearGLError(&error);
|
|
||||||
|
|
||||||
free(zeros);
|
free(zeros);
|
||||||
SetImageDataStatus(imageTarget, level, WebGLImageDataStatus::InitializedImageData);
|
SetImageDataStatus(imageTarget, level, WebGLImageDataStatus::InitializedImageData);
|
||||||
|
|
|
@ -44,6 +44,8 @@ if CONFIG['MOZ_WEBGL']:
|
||||||
'WebGLContextVertices.cpp',
|
'WebGLContextVertices.cpp',
|
||||||
'WebGLElementArrayCache.cpp',
|
'WebGLElementArrayCache.cpp',
|
||||||
'WebGLExtensionBase.cpp',
|
'WebGLExtensionBase.cpp',
|
||||||
|
'WebGLExtensionColorBufferFloat.cpp',
|
||||||
|
'WebGLExtensionColorBufferHalfFloat.cpp',
|
||||||
'WebGLExtensionCompressedTextureATC.cpp',
|
'WebGLExtensionCompressedTextureATC.cpp',
|
||||||
'WebGLExtensionCompressedTexturePVRTC.cpp',
|
'WebGLExtensionCompressedTexturePVRTC.cpp',
|
||||||
'WebGLExtensionCompressedTextureS3TC.cpp',
|
'WebGLExtensionCompressedTextureS3TC.cpp',
|
||||||
|
|
|
@ -147,7 +147,7 @@ var files = [
|
||||||
frames: 33297,
|
frames: 33297,
|
||||||
sampleRate: 48000,
|
sampleRate: 48000,
|
||||||
duration: 0.693,
|
duration: 0.693,
|
||||||
fuzzTolerance: 3,
|
fuzzTolerance: 5,
|
||||||
fuzzToleranceMobile: 1388
|
fuzzToleranceMobile: 1388
|
||||||
},
|
},
|
||||||
// An ogg file, 48khz, stereo
|
// An ogg file, 48khz, stereo
|
||||||
|
|
|
@ -56,7 +56,7 @@ void EbmlComposer::GenerateHeader()
|
||||||
}
|
}
|
||||||
// The Recording length is unknow and ignore write the whole Segment element size
|
// The Recording length is unknow and ignore write the whole Segment element size
|
||||||
}
|
}
|
||||||
MOZ_ASSERT_IF(ebml.offset > DEFAULT_HEADER_SIZE + mCodecPrivateData.Length(),
|
MOZ_ASSERT(ebml.offset <= DEFAULT_HEADER_SIZE + mCodecPrivateData.Length(),
|
||||||
"write more data > EBML_BUFFER_SIZE");
|
"write more data > EBML_BUFFER_SIZE");
|
||||||
mClusterBuffs.AppendElement();
|
mClusterBuffs.AppendElement();
|
||||||
mClusterBuffs.LastElement().SetLength(ebml.offset);
|
mClusterBuffs.LastElement().SetLength(ebml.offset);
|
||||||
|
@ -117,7 +117,7 @@ EbmlComposer::WriteSimpleBlock(EncodedFrame* aFrame)
|
||||||
0, 0, (unsigned char*)aFrame->GetFrameData().Elements(),
|
0, 0, (unsigned char*)aFrame->GetFrameData().Elements(),
|
||||||
aFrame->GetFrameData().Length());
|
aFrame->GetFrameData().Length());
|
||||||
}
|
}
|
||||||
MOZ_ASSERT_IF(ebml.offset > DEFAULT_HEADER_SIZE + aFrame->GetFrameData().Length(),
|
MOZ_ASSERT(ebml.offset <= DEFAULT_HEADER_SIZE + aFrame->GetFrameData().Length(),
|
||||||
"write more data > EBML_BUFFER_SIZE");
|
"write more data > EBML_BUFFER_SIZE");
|
||||||
mClusterBuffs.LastElement().SetLength(ebml.offset);
|
mClusterBuffs.LastElement().SetLength(ebml.offset);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
#include "nsFrameTraversal.h"
|
#include "nsFrameTraversal.h"
|
||||||
#include "nsEventDispatcher.h"
|
#include "nsEventDispatcher.h"
|
||||||
#include "nsEventStateManager.h"
|
#include "nsEventStateManager.h"
|
||||||
#include "nsIMEStateManager.h"
|
|
||||||
#include "nsIWebNavigation.h"
|
#include "nsIWebNavigation.h"
|
||||||
#include "nsCaret.h"
|
#include "nsCaret.h"
|
||||||
#include "nsIBaseWindow.h"
|
#include "nsIBaseWindow.h"
|
||||||
|
@ -41,6 +40,7 @@
|
||||||
|
|
||||||
#include "mozilla/ContentEvents.h"
|
#include "mozilla/ContentEvents.h"
|
||||||
#include "mozilla/dom/Element.h"
|
#include "mozilla/dom/Element.h"
|
||||||
|
#include "mozilla/IMEStateManager.h"
|
||||||
#include "mozilla/LookAndFeel.h"
|
#include "mozilla/LookAndFeel.h"
|
||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
#include "mozilla/Services.h"
|
#include "mozilla/Services.h"
|
||||||
|
@ -933,7 +933,7 @@ nsFocusManager::WindowHidden(nsIDOMWindow* aWindow)
|
||||||
|
|
||||||
nsPresContext* focusedPresContext =
|
nsPresContext* focusedPresContext =
|
||||||
presShell ? presShell->GetPresContext() : nullptr;
|
presShell ? presShell->GetPresContext() : nullptr;
|
||||||
nsIMEStateManager::OnChangeFocus(focusedPresContext, nullptr,
|
IMEStateManager::OnChangeFocus(focusedPresContext, nullptr,
|
||||||
GetFocusMoveActionCause(0));
|
GetFocusMoveActionCause(0));
|
||||||
if (presShell) {
|
if (presShell) {
|
||||||
SetCaretVisible(presShell, false, nullptr);
|
SetCaretVisible(presShell, false, nullptr);
|
||||||
|
@ -1529,7 +1529,7 @@ nsFocusManager::Blur(nsPIDOMWindow* aWindowToClear,
|
||||||
|
|
||||||
nsPresContext* focusedPresContext =
|
nsPresContext* focusedPresContext =
|
||||||
mActiveWindow ? presShell->GetPresContext() : nullptr;
|
mActiveWindow ? presShell->GetPresContext() : nullptr;
|
||||||
nsIMEStateManager::OnChangeFocus(focusedPresContext, nullptr,
|
IMEStateManager::OnChangeFocus(focusedPresContext, nullptr,
|
||||||
GetFocusMoveActionCause(0));
|
GetFocusMoveActionCause(0));
|
||||||
|
|
||||||
// now adjust the actual focus, by clearing the fields in the focus manager
|
// now adjust the actual focus, by clearing the fields in the focus manager
|
||||||
|
@ -1746,11 +1746,11 @@ nsFocusManager::Focus(nsPIDOMWindow* aWindow,
|
||||||
// document and then the window.
|
// document and then the window.
|
||||||
if (aIsNewDocument) {
|
if (aIsNewDocument) {
|
||||||
nsIDocument* doc = aWindow->GetExtantDoc();
|
nsIDocument* doc = aWindow->GetExtantDoc();
|
||||||
// The focus change should be notified to nsIMEStateManager from here if
|
// The focus change should be notified to IMEStateManager from here if
|
||||||
// the focused content is a designMode editor since any content won't
|
// the focused content is a designMode editor since any content won't
|
||||||
// receive focus event.
|
// receive focus event.
|
||||||
if (doc && doc->HasFlag(NODE_IS_EDITABLE)) {
|
if (doc && doc->HasFlag(NODE_IS_EDITABLE)) {
|
||||||
nsIMEStateManager::OnChangeFocus(presShell->GetPresContext(), nullptr,
|
IMEStateManager::OnChangeFocus(presShell->GetPresContext(), nullptr,
|
||||||
GetFocusMoveActionCause(aFlags));
|
GetFocusMoveActionCause(aFlags));
|
||||||
}
|
}
|
||||||
if (doc)
|
if (doc)
|
||||||
|
@ -1796,7 +1796,7 @@ nsFocusManager::Focus(nsPIDOMWindow* aWindow,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nsIMEStateManager::OnChangeFocus(presContext, aContent,
|
IMEStateManager::OnChangeFocus(presContext, aContent,
|
||||||
GetFocusMoveActionCause(aFlags));
|
GetFocusMoveActionCause(aFlags));
|
||||||
|
|
||||||
// as long as this focus wasn't because a window was raised, update the
|
// as long as this focus wasn't because a window was raised, update the
|
||||||
|
@ -1810,7 +1810,7 @@ nsFocusManager::Focus(nsPIDOMWindow* aWindow,
|
||||||
aContent, aFlags & FOCUSMETHOD_MASK,
|
aContent, aFlags & FOCUSMETHOD_MASK,
|
||||||
aWindowRaised, isRefocus);
|
aWindowRaised, isRefocus);
|
||||||
} else {
|
} else {
|
||||||
nsIMEStateManager::OnChangeFocus(presContext, nullptr,
|
IMEStateManager::OnChangeFocus(presContext, nullptr,
|
||||||
GetFocusMoveActionCause(aFlags));
|
GetFocusMoveActionCause(aFlags));
|
||||||
if (!aWindowRaised) {
|
if (!aWindowRaised) {
|
||||||
aWindow->UpdateCommands(NS_LITERAL_STRING("focus"));
|
aWindow->UpdateCommands(NS_LITERAL_STRING("focus"));
|
||||||
|
@ -1834,7 +1834,7 @@ nsFocusManager::Focus(nsPIDOMWindow* aWindow,
|
||||||
}
|
}
|
||||||
|
|
||||||
nsPresContext* presContext = presShell->GetPresContext();
|
nsPresContext* presContext = presShell->GetPresContext();
|
||||||
nsIMEStateManager::OnChangeFocus(presContext, nullptr,
|
IMEStateManager::OnChangeFocus(presContext, nullptr,
|
||||||
GetFocusMoveActionCause(aFlags));
|
GetFocusMoveActionCause(aFlags));
|
||||||
|
|
||||||
if (!aWindowRaised)
|
if (!aWindowRaised)
|
||||||
|
|
|
@ -24,11 +24,24 @@ using namespace mozilla;
|
||||||
|
|
||||||
StaticRefPtr<nsWindowMemoryReporter> sWindowReporter;
|
StaticRefPtr<nsWindowMemoryReporter> sWindowReporter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Don't trigger a ghost window check when a DOM window is detached if we've
|
||||||
|
* run it this recently.
|
||||||
|
*/
|
||||||
|
const int32_t kTimeBetweenChecks = 45; /* seconds */
|
||||||
|
|
||||||
nsWindowMemoryReporter::nsWindowMemoryReporter()
|
nsWindowMemoryReporter::nsWindowMemoryReporter()
|
||||||
: mCheckForGhostWindowsCallbackPending(false)
|
: mLastCheckForGhostWindows(TimeStamp::NowLoRes()),
|
||||||
|
mCycleCollectorIsRunning(false),
|
||||||
|
mCheckTimerWaitingForCCEnd(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsWindowMemoryReporter::~nsWindowMemoryReporter()
|
||||||
|
{
|
||||||
|
KillCheckTimer();
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS3(nsWindowMemoryReporter, nsIMemoryReporter, nsIObserver,
|
NS_IMPL_ISUPPORTS3(nsWindowMemoryReporter, nsIMemoryReporter, nsIObserver,
|
||||||
nsSupportsWeakReference)
|
nsSupportsWeakReference)
|
||||||
|
|
||||||
|
@ -105,6 +118,10 @@ nsWindowMemoryReporter::Init()
|
||||||
/* weakRef = */ true);
|
/* weakRef = */ true);
|
||||||
os->AddObserver(sWindowReporter, "after-minimize-memory-usage",
|
os->AddObserver(sWindowReporter, "after-minimize-memory-usage",
|
||||||
/* weakRef = */ true);
|
/* weakRef = */ true);
|
||||||
|
os->AddObserver(sWindowReporter, "cycle-collector-begin",
|
||||||
|
/* weakRef = */ true);
|
||||||
|
os->AddObserver(sWindowReporter, "cycle-collector-end",
|
||||||
|
/* weakRef = */ true);
|
||||||
}
|
}
|
||||||
|
|
||||||
RegisterStrongMemoryReporter(new GhostWindowsReporter());
|
RegisterStrongMemoryReporter(new GhostWindowsReporter());
|
||||||
|
@ -608,6 +625,18 @@ nsWindowMemoryReporter::Observe(nsISupports *aSubject, const char *aTopic,
|
||||||
ObserveDOMWindowDetached(aSubject);
|
ObserveDOMWindowDetached(aSubject);
|
||||||
} else if (!strcmp(aTopic, "after-minimize-memory-usage")) {
|
} else if (!strcmp(aTopic, "after-minimize-memory-usage")) {
|
||||||
ObserveAfterMinimizeMemoryUsage();
|
ObserveAfterMinimizeMemoryUsage();
|
||||||
|
} else if (!strcmp(aTopic, "cycle-collector-begin")) {
|
||||||
|
if (mCheckTimer) {
|
||||||
|
mCheckTimerWaitingForCCEnd = true;
|
||||||
|
KillCheckTimer();
|
||||||
|
}
|
||||||
|
mCycleCollectorIsRunning = true;
|
||||||
|
} else if (!strcmp(aTopic, "cycle-collector-end")) {
|
||||||
|
mCycleCollectorIsRunning = false;
|
||||||
|
if (mCheckTimerWaitingForCCEnd) {
|
||||||
|
mCheckTimerWaitingForCCEnd = false;
|
||||||
|
AsyncCheckForGhostWindows();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
MOZ_ASSERT(false);
|
MOZ_ASSERT(false);
|
||||||
}
|
}
|
||||||
|
@ -626,12 +655,44 @@ nsWindowMemoryReporter::ObserveDOMWindowDetached(nsISupports* aWindow)
|
||||||
|
|
||||||
mDetachedWindows.Put(weakWindow, TimeStamp());
|
mDetachedWindows.Put(weakWindow, TimeStamp());
|
||||||
|
|
||||||
if (!mCheckForGhostWindowsCallbackPending) {
|
AsyncCheckForGhostWindows();
|
||||||
nsCOMPtr<nsIRunnable> runnable =
|
}
|
||||||
NS_NewRunnableMethod(this,
|
|
||||||
&nsWindowMemoryReporter::CheckForGhostWindowsCallback);
|
// static
|
||||||
NS_DispatchToCurrentThread(runnable);
|
void
|
||||||
mCheckForGhostWindowsCallbackPending = true;
|
nsWindowMemoryReporter::CheckTimerFired(nsITimer* aTimer, void* aClosure)
|
||||||
|
{
|
||||||
|
if (sWindowReporter) {
|
||||||
|
MOZ_ASSERT(!sWindowReporter->mCycleCollectorIsRunning);
|
||||||
|
sWindowReporter->CheckForGhostWindows();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsWindowMemoryReporter::AsyncCheckForGhostWindows()
|
||||||
|
{
|
||||||
|
if (mCheckTimer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mCycleCollectorIsRunning) {
|
||||||
|
mCheckTimerWaitingForCCEnd = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If more than kTimeBetweenChecks seconds have elapsed since the last check,
|
||||||
|
// timerDelay is 0. Otherwise, it is kTimeBetweenChecks, reduced by the time
|
||||||
|
// since the last check. Reducing the delay by the time since the last check
|
||||||
|
// prevents the timer from being completely starved if it is repeatedly killed
|
||||||
|
// and restarted.
|
||||||
|
int32_t timeSinceLastCheck = (TimeStamp::NowLoRes() - mLastCheckForGhostWindows).ToSeconds();
|
||||||
|
int32_t timerDelay = (kTimeBetweenChecks - std::min(timeSinceLastCheck, kTimeBetweenChecks)) * PR_MSEC_PER_SEC;
|
||||||
|
|
||||||
|
CallCreateInstance<nsITimer>("@mozilla.org/timer;1", getter_AddRefs(mCheckTimer));
|
||||||
|
|
||||||
|
if (mCheckTimer) {
|
||||||
|
mCheckTimer->InitWithFuncCallback(CheckTimerFired, nullptr,
|
||||||
|
timerDelay, nsITimer::TYPE_ONE_SHOT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -664,13 +725,6 @@ nsWindowMemoryReporter::ObserveAfterMinimizeMemoryUsage()
|
||||||
&minTimeStamp);
|
&minTimeStamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
nsWindowMemoryReporter::CheckForGhostWindowsCallback()
|
|
||||||
{
|
|
||||||
mCheckForGhostWindowsCallbackPending = false;
|
|
||||||
CheckForGhostWindows();
|
|
||||||
}
|
|
||||||
|
|
||||||
struct CheckForGhostWindowsEnumeratorData
|
struct CheckForGhostWindowsEnumeratorData
|
||||||
{
|
{
|
||||||
nsTHashtable<nsCStringHashKey> *nonDetachedDomains;
|
nsTHashtable<nsCStringHashKey> *nonDetachedDomains;
|
||||||
|
@ -808,6 +862,9 @@ nsWindowMemoryReporter::CheckForGhostWindows(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mLastCheckForGhostWindows = TimeStamp::NowLoRes();
|
||||||
|
KillCheckTimer();
|
||||||
|
|
||||||
nsTHashtable<nsCStringHashKey> nonDetachedWindowDomains;
|
nsTHashtable<nsCStringHashKey> nonDetachedWindowDomains;
|
||||||
|
|
||||||
// Populate nonDetachedWindowDomains.
|
// Populate nonDetachedWindowDomains.
|
||||||
|
@ -820,7 +877,7 @@ nsWindowMemoryReporter::CheckForGhostWindows(
|
||||||
// if it's not null.
|
// if it's not null.
|
||||||
CheckForGhostWindowsEnumeratorData ghostEnumData =
|
CheckForGhostWindowsEnumeratorData ghostEnumData =
|
||||||
{ &nonDetachedWindowDomains, aOutGhostIDs, tldService,
|
{ &nonDetachedWindowDomains, aOutGhostIDs, tldService,
|
||||||
GetGhostTimeout(), TimeStamp::Now() };
|
GetGhostTimeout(), mLastCheckForGhostWindows };
|
||||||
mDetachedWindows.Enumerate(CheckForGhostWindowsEnumerator,
|
mDetachedWindows.Enumerate(CheckForGhostWindowsEnumerator,
|
||||||
&ghostEnumData);
|
&ghostEnumData);
|
||||||
}
|
}
|
||||||
|
@ -836,6 +893,15 @@ nsWindowMemoryReporter::GhostWindowsReporter::DistinguishedAmount()
|
||||||
return ghostWindows.Count();
|
return ghostWindows.Count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsWindowMemoryReporter::KillCheckTimer()
|
||||||
|
{
|
||||||
|
if (mCheckTimer) {
|
||||||
|
mCheckTimer->Cancel();
|
||||||
|
mCheckTimer = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
static PLDHashOperator
|
static PLDHashOperator
|
||||||
UnlinkGhostWindowsEnumerator(nsUint64HashKey* aIDHashKey, void *)
|
UnlinkGhostWindowsEnumerator(nsUint64HashKey* aIDHashKey, void *)
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include "nsIMemoryReporter.h"
|
#include "nsIMemoryReporter.h"
|
||||||
#include "nsIObserver.h"
|
#include "nsIObserver.h"
|
||||||
|
#include "nsITimer.h"
|
||||||
#include "nsDataHashtable.h"
|
#include "nsDataHashtable.h"
|
||||||
#include "nsWeakReference.h"
|
#include "nsWeakReference.h"
|
||||||
#include "nsAutoPtr.h"
|
#include "nsAutoPtr.h"
|
||||||
|
@ -139,6 +140,8 @@ public:
|
||||||
|
|
||||||
static void Init();
|
static void Init();
|
||||||
|
|
||||||
|
~nsWindowMemoryReporter();
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
/**
|
/**
|
||||||
* Unlink all known ghost windows, to enable investigating what caused them
|
* Unlink all known ghost windows, to enable investigating what caused them
|
||||||
|
@ -187,13 +190,6 @@ private:
|
||||||
void ObserveDOMWindowDetached(nsISupports* aWindow);
|
void ObserveDOMWindowDetached(nsISupports* aWindow);
|
||||||
void ObserveAfterMinimizeMemoryUsage();
|
void ObserveAfterMinimizeMemoryUsage();
|
||||||
|
|
||||||
/**
|
|
||||||
* When we observe a DOM window being detached, we enqueue an asynchronous
|
|
||||||
* event which calls this method. This method then calls
|
|
||||||
* CheckForGhostWindows.
|
|
||||||
*/
|
|
||||||
void CheckForGhostWindowsCallback();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Iterate over all weak window pointers in mDetachedWindows and update our
|
* Iterate over all weak window pointers in mDetachedWindows and update our
|
||||||
* accounting of which windows meet ghost criterion (2).
|
* accounting of which windows meet ghost criterion (2).
|
||||||
|
@ -209,6 +205,19 @@ private:
|
||||||
*/
|
*/
|
||||||
void CheckForGhostWindows(nsTHashtable<nsUint64HashKey> *aOutGhostIDs = nullptr);
|
void CheckForGhostWindows(nsTHashtable<nsUint64HashKey> *aOutGhostIDs = nullptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Eventually do a check for ghost windows, if we haven't done one recently
|
||||||
|
* and we aren't already planning to do one soon.
|
||||||
|
*/
|
||||||
|
void AsyncCheckForGhostWindows();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kill the check timer, if it exists.
|
||||||
|
*/
|
||||||
|
void KillCheckTimer();
|
||||||
|
|
||||||
|
static void CheckTimerFired(nsITimer* aTimer, void* aClosure);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps a weak reference to a detached window (nsIWeakReference) to the time
|
* Maps a weak reference to a detached window (nsIWeakReference) to the time
|
||||||
* when we observed that the window met ghost criterion (2) above.
|
* when we observed that the window met ghost criterion (2) above.
|
||||||
|
@ -222,9 +231,16 @@ private:
|
||||||
nsDataHashtable<nsISupportsHashKey, mozilla::TimeStamp> mDetachedWindows;
|
nsDataHashtable<nsISupportsHashKey, mozilla::TimeStamp> mDetachedWindows;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* True if we have an asynchronous call to CheckForGhostWindows pending.
|
* Track the last time we ran CheckForGhostWindows(), to avoid running it
|
||||||
|
* too often after a DOM window is detached.
|
||||||
*/
|
*/
|
||||||
bool mCheckForGhostWindowsCallbackPending;
|
mozilla::TimeStamp mLastCheckForGhostWindows;
|
||||||
|
|
||||||
|
nsCOMPtr<nsITimer> mCheckTimer;
|
||||||
|
|
||||||
|
bool mCycleCollectorIsRunning;
|
||||||
|
|
||||||
|
bool mCheckTimerWaitingForCCEnd;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // nsWindowMemoryReporter_h__
|
#endif // nsWindowMemoryReporter_h__
|
||||||
|
|
|
@ -1342,6 +1342,16 @@ DOMInterfaces = {
|
||||||
'headerFile': 'WebGLExtensions.h'
|
'headerFile': 'WebGLExtensions.h'
|
||||||
},
|
},
|
||||||
|
|
||||||
|
'WebGLExtensionColorBufferFloat': {
|
||||||
|
'nativeType': 'mozilla::WebGLExtensionColorBufferFloat',
|
||||||
|
'headerFile': 'WebGLExtensions.h'
|
||||||
|
},
|
||||||
|
|
||||||
|
'WebGLExtensionColorBufferHalfFloat': {
|
||||||
|
'nativeType': 'mozilla::WebGLExtensionColorBufferHalfFloat',
|
||||||
|
'headerFile': 'WebGLExtensions.h'
|
||||||
|
},
|
||||||
|
|
||||||
'WebGLExtensionDrawBuffers': {
|
'WebGLExtensionDrawBuffers': {
|
||||||
'nativeType': 'mozilla::WebGLExtensionDrawBuffers',
|
'nativeType': 'mozilla::WebGLExtensionDrawBuffers',
|
||||||
'headerFile': 'WebGLExtensions.h'
|
'headerFile': 'WebGLExtensions.h'
|
||||||
|
|
|
@ -0,0 +1,537 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=2 sw=2 et tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "IMEContentObserver.h"
|
||||||
|
#include "mozilla/IMEStateManager.h"
|
||||||
|
#include "mozilla/dom/Element.h"
|
||||||
|
#include "nsAutoPtr.h"
|
||||||
|
#include "nsAsyncDOMEvent.h"
|
||||||
|
#include "nsContentEventHandler.h"
|
||||||
|
#include "nsContentUtils.h"
|
||||||
|
#include "nsGkAtoms.h"
|
||||||
|
#include "nsIAtom.h"
|
||||||
|
#include "nsIContent.h"
|
||||||
|
#include "nsIDocument.h"
|
||||||
|
#include "nsIDOMDocument.h"
|
||||||
|
#include "nsIDOMRange.h"
|
||||||
|
#include "nsIFrame.h"
|
||||||
|
#include "nsINode.h"
|
||||||
|
#include "nsIPresShell.h"
|
||||||
|
#include "nsISelectionController.h"
|
||||||
|
#include "nsISelectionPrivate.h"
|
||||||
|
#include "nsISupports.h"
|
||||||
|
#include "nsIWidget.h"
|
||||||
|
#include "nsPresContext.h"
|
||||||
|
#include "nsThreadUtils.h"
|
||||||
|
#include "nsWeakReference.h"
|
||||||
|
#include "TextComposition.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
using namespace widget;
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS5(IMEContentObserver,
|
||||||
|
nsIMutationObserver,
|
||||||
|
nsISelectionListener,
|
||||||
|
nsIReflowObserver,
|
||||||
|
nsIScrollObserver,
|
||||||
|
nsISupportsWeakReference)
|
||||||
|
|
||||||
|
IMEContentObserver::IMEContentObserver()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IMEContentObserver::Init(nsIWidget* aWidget,
|
||||||
|
nsPresContext* aPresContext,
|
||||||
|
nsIContent* aContent)
|
||||||
|
{
|
||||||
|
mWidget = aWidget;
|
||||||
|
mEditableNode = IMEStateManager::GetRootEditableNode(aPresContext, aContent);
|
||||||
|
if (!mEditableNode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIPresShell* presShell = aPresContext->PresShell();
|
||||||
|
|
||||||
|
// get selection and root content
|
||||||
|
nsCOMPtr<nsISelectionController> selCon;
|
||||||
|
if (mEditableNode->IsNodeOfType(nsINode::eCONTENT)) {
|
||||||
|
nsIFrame* frame =
|
||||||
|
static_cast<nsIContent*>(mEditableNode.get())->GetPrimaryFrame();
|
||||||
|
NS_ENSURE_TRUE_VOID(frame);
|
||||||
|
|
||||||
|
frame->GetSelectionController(aPresContext,
|
||||||
|
getter_AddRefs(selCon));
|
||||||
|
} else {
|
||||||
|
// mEditableNode is a document
|
||||||
|
selCon = do_QueryInterface(presShell);
|
||||||
|
}
|
||||||
|
NS_ENSURE_TRUE_VOID(selCon);
|
||||||
|
|
||||||
|
selCon->GetSelection(nsISelectionController::SELECTION_NORMAL,
|
||||||
|
getter_AddRefs(mSelection));
|
||||||
|
NS_ENSURE_TRUE_VOID(mSelection);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIDOMRange> selDomRange;
|
||||||
|
if (NS_SUCCEEDED(mSelection->GetRangeAt(0, getter_AddRefs(selDomRange)))) {
|
||||||
|
nsRange* selRange = static_cast<nsRange*>(selDomRange.get());
|
||||||
|
NS_ENSURE_TRUE_VOID(selRange && selRange->GetStartParent());
|
||||||
|
|
||||||
|
mRootContent = selRange->GetStartParent()->
|
||||||
|
GetSelectionRootContent(presShell);
|
||||||
|
} else {
|
||||||
|
mRootContent = mEditableNode->GetSelectionRootContent(presShell);
|
||||||
|
}
|
||||||
|
if (!mRootContent && mEditableNode->IsNodeOfType(nsINode::eDOCUMENT)) {
|
||||||
|
// The document node is editable, but there are no contents, this document
|
||||||
|
// is not editable.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NS_ENSURE_TRUE_VOID(mRootContent);
|
||||||
|
|
||||||
|
if (IMEStateManager::IsTestingIME()) {
|
||||||
|
nsIDocument* doc = aPresContext->Document();
|
||||||
|
(new nsAsyncDOMEvent(doc, NS_LITERAL_STRING("MozIMEFocusIn"),
|
||||||
|
false, false))->RunDOMEventWhenSafe();
|
||||||
|
}
|
||||||
|
|
||||||
|
aWidget->NotifyIME(IMENotification(NOTIFY_IME_OF_FOCUS));
|
||||||
|
|
||||||
|
// NOTIFY_IME_OF_FOCUS might cause recreating IMEContentObserver
|
||||||
|
// instance via IMEStateManager::UpdateIMEState(). So, this
|
||||||
|
// instance might already have been destroyed, check it.
|
||||||
|
if (!mRootContent) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mDocShell = aPresContext->GetDocShell();
|
||||||
|
|
||||||
|
ObserveEditableNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IMEContentObserver::ObserveEditableNode()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mSelection);
|
||||||
|
MOZ_ASSERT(mRootContent);
|
||||||
|
|
||||||
|
mUpdatePreference = mWidget->GetIMEUpdatePreference();
|
||||||
|
if (mUpdatePreference.WantSelectionChange()) {
|
||||||
|
// add selection change listener
|
||||||
|
nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(mSelection));
|
||||||
|
NS_ENSURE_TRUE_VOID(selPrivate);
|
||||||
|
nsresult rv = selPrivate->AddSelectionListener(this);
|
||||||
|
NS_ENSURE_SUCCESS_VOID(rv);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mUpdatePreference.WantTextChange()) {
|
||||||
|
// add text change observer
|
||||||
|
mRootContent->AddMutationObserver(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mUpdatePreference.WantPositionChanged() && mDocShell) {
|
||||||
|
// Add scroll position listener and reflow observer to detect position and
|
||||||
|
// size changes
|
||||||
|
mDocShell->AddWeakScrollObserver(this);
|
||||||
|
mDocShell->AddWeakReflowObserver(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IMEContentObserver::Destroy()
|
||||||
|
{
|
||||||
|
// If CreateTextStateManager failed, mRootContent will be null,
|
||||||
|
// and we should not call NotifyIME(IMENotification(NOTIFY_IME_OF_BLUR))
|
||||||
|
if (mRootContent) {
|
||||||
|
if (IMEStateManager::IsTestingIME() && mEditableNode) {
|
||||||
|
nsIDocument* doc = mEditableNode->OwnerDoc();
|
||||||
|
(new nsAsyncDOMEvent(doc, NS_LITERAL_STRING("MozIMEFocusOut"),
|
||||||
|
false, false))->RunDOMEventWhenSafe();
|
||||||
|
}
|
||||||
|
mWidget->NotifyIME(IMENotification(NOTIFY_IME_OF_BLUR));
|
||||||
|
}
|
||||||
|
// Even if there are some pending notification, it'll never notify the widget.
|
||||||
|
mWidget = nullptr;
|
||||||
|
if (mUpdatePreference.WantSelectionChange() && mSelection) {
|
||||||
|
nsCOMPtr<nsISelectionPrivate> selPrivate(do_QueryInterface(mSelection));
|
||||||
|
if (selPrivate) {
|
||||||
|
selPrivate->RemoveSelectionListener(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mSelection = nullptr;
|
||||||
|
if (mUpdatePreference.WantTextChange() && mRootContent) {
|
||||||
|
mRootContent->RemoveMutationObserver(this);
|
||||||
|
}
|
||||||
|
if (mUpdatePreference.WantPositionChanged() && mDocShell) {
|
||||||
|
mDocShell->RemoveWeakScrollObserver(this);
|
||||||
|
mDocShell->RemoveWeakReflowObserver(this);
|
||||||
|
}
|
||||||
|
mRootContent = nullptr;
|
||||||
|
mEditableNode = nullptr;
|
||||||
|
mDocShell = nullptr;
|
||||||
|
mUpdatePreference.mWantUpdates = nsIMEUpdatePreference::NOTIFY_NOTHING;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
IMEContentObserver::IsManaging(nsPresContext* aPresContext,
|
||||||
|
nsIContent* aContent)
|
||||||
|
{
|
||||||
|
if (!mSelection || !mRootContent || !mEditableNode) {
|
||||||
|
return false; // failed to initialize.
|
||||||
|
}
|
||||||
|
if (!mRootContent->IsInDoc()) {
|
||||||
|
return false; // the focused editor has already been reframed.
|
||||||
|
}
|
||||||
|
return mEditableNode == IMEStateManager::GetRootEditableNode(aPresContext,
|
||||||
|
aContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
IMEContentObserver::IsEditorHandlingEventForComposition() const
|
||||||
|
{
|
||||||
|
if (!mWidget) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
nsRefPtr<TextComposition> composition =
|
||||||
|
IMEStateManager::GetTextCompositionFor(mWidget);
|
||||||
|
if (!composition) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return composition->IsEditorHandlingEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
IMEContentObserver::GetSelectionAndRoot(nsISelection** aSelection,
|
||||||
|
nsIContent** aRootContent) const
|
||||||
|
{
|
||||||
|
if (!mEditableNode || !mSelection) {
|
||||||
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_ASSERTION(mSelection && mRootContent, "uninitialized content observer");
|
||||||
|
NS_ADDREF(*aSelection = mSelection);
|
||||||
|
NS_ADDREF(*aRootContent = mRootContent);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper class, used for selection change notification
|
||||||
|
class SelectionChangeEvent : public nsRunnable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SelectionChangeEvent(IMEContentObserver* aDispatcher,
|
||||||
|
bool aCausedByComposition)
|
||||||
|
: mDispatcher(aDispatcher)
|
||||||
|
, mCausedByComposition(aCausedByComposition)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mDispatcher);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHOD Run()
|
||||||
|
{
|
||||||
|
if (mDispatcher->GetWidget()) {
|
||||||
|
IMENotification notification(NOTIFY_IME_OF_SELECTION_CHANGE);
|
||||||
|
notification.mSelectionChangeData.mCausedByComposition =
|
||||||
|
mCausedByComposition;
|
||||||
|
mDispatcher->GetWidget()->NotifyIME(notification);
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
nsRefPtr<IMEContentObserver> mDispatcher;
|
||||||
|
bool mCausedByComposition;
|
||||||
|
};
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
IMEContentObserver::NotifySelectionChanged(nsIDOMDocument* aDOMDocument,
|
||||||
|
nsISelection* aSelection,
|
||||||
|
int16_t aReason)
|
||||||
|
{
|
||||||
|
bool causedByComposition = IsEditorHandlingEventForComposition();
|
||||||
|
if (causedByComposition &&
|
||||||
|
!mUpdatePreference.WantChangesCausedByComposition()) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t count = 0;
|
||||||
|
nsresult rv = aSelection->GetRangeCount(&count);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
if (count > 0 && mWidget) {
|
||||||
|
nsContentUtils::AddScriptRunner(
|
||||||
|
new SelectionChangeEvent(this, causedByComposition));
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper class, used for position change notification
|
||||||
|
class PositionChangeEvent MOZ_FINAL : public nsRunnable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PositionChangeEvent(IMEContentObserver* aDispatcher)
|
||||||
|
: mDispatcher(aDispatcher)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mDispatcher);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHOD Run()
|
||||||
|
{
|
||||||
|
if (mDispatcher->GetWidget()) {
|
||||||
|
mDispatcher->GetWidget()->NotifyIME(
|
||||||
|
IMENotification(NOTIFY_IME_OF_POSITION_CHANGE));
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
nsRefPtr<IMEContentObserver> mDispatcher;
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
IMEContentObserver::ScrollPositionChanged()
|
||||||
|
{
|
||||||
|
if (mWidget) {
|
||||||
|
nsContentUtils::AddScriptRunner(new PositionChangeEvent(this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
IMEContentObserver::Reflow(DOMHighResTimeStamp aStart,
|
||||||
|
DOMHighResTimeStamp aEnd)
|
||||||
|
{
|
||||||
|
if (mWidget) {
|
||||||
|
nsContentUtils::AddScriptRunner(new PositionChangeEvent(this));
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
IMEContentObserver::ReflowInterruptible(DOMHighResTimeStamp aStart,
|
||||||
|
DOMHighResTimeStamp aEnd)
|
||||||
|
{
|
||||||
|
if (mWidget) {
|
||||||
|
nsContentUtils::AddScriptRunner(new PositionChangeEvent(this));
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper class, used for text change notification
|
||||||
|
class TextChangeEvent : public nsRunnable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TextChangeEvent(IMEContentObserver* aDispatcher,
|
||||||
|
uint32_t aStart, uint32_t aOldEnd, uint32_t aNewEnd,
|
||||||
|
bool aCausedByComposition)
|
||||||
|
: mDispatcher(aDispatcher)
|
||||||
|
, mStart(aStart)
|
||||||
|
, mOldEnd(aOldEnd)
|
||||||
|
, mNewEnd(aNewEnd)
|
||||||
|
, mCausedByComposition(aCausedByComposition)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(mDispatcher);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHOD Run()
|
||||||
|
{
|
||||||
|
if (mDispatcher->GetWidget()) {
|
||||||
|
IMENotification notification(NOTIFY_IME_OF_TEXT_CHANGE);
|
||||||
|
notification.mTextChangeData.mStartOffset = mStart;
|
||||||
|
notification.mTextChangeData.mOldEndOffset = mOldEnd;
|
||||||
|
notification.mTextChangeData.mNewEndOffset = mNewEnd;
|
||||||
|
notification.mTextChangeData.mCausedByComposition = mCausedByComposition;
|
||||||
|
mDispatcher->GetWidget()->NotifyIME(notification);
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
nsRefPtr<IMEContentObserver> mDispatcher;
|
||||||
|
uint32_t mStart, mOldEnd, mNewEnd;
|
||||||
|
bool mCausedByComposition;
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
IMEContentObserver::CharacterDataChanged(nsIDocument* aDocument,
|
||||||
|
nsIContent* aContent,
|
||||||
|
CharacterDataChangeInfo* aInfo)
|
||||||
|
{
|
||||||
|
NS_ASSERTION(aContent->IsNodeOfType(nsINode::eTEXT),
|
||||||
|
"character data changed for non-text node");
|
||||||
|
|
||||||
|
bool causedByComposition = IsEditorHandlingEventForComposition();
|
||||||
|
if (causedByComposition &&
|
||||||
|
!mUpdatePreference.WantChangesCausedByComposition()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t offset = 0;
|
||||||
|
// get offsets of change and fire notification
|
||||||
|
nsresult rv =
|
||||||
|
nsContentEventHandler::GetFlatTextOffsetOfRange(mRootContent, aContent,
|
||||||
|
aInfo->mChangeStart,
|
||||||
|
&offset);
|
||||||
|
NS_ENSURE_SUCCESS_VOID(rv);
|
||||||
|
|
||||||
|
uint32_t oldEnd = offset + aInfo->mChangeEnd - aInfo->mChangeStart;
|
||||||
|
uint32_t newEnd = offset + aInfo->mReplaceLength;
|
||||||
|
|
||||||
|
nsContentUtils::AddScriptRunner(
|
||||||
|
new TextChangeEvent(this, offset, oldEnd, newEnd, causedByComposition));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IMEContentObserver::NotifyContentAdded(nsINode* aContainer,
|
||||||
|
int32_t aStartIndex,
|
||||||
|
int32_t aEndIndex)
|
||||||
|
{
|
||||||
|
bool causedByComposition = IsEditorHandlingEventForComposition();
|
||||||
|
if (causedByComposition &&
|
||||||
|
!mUpdatePreference.WantChangesCausedByComposition()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t offset = 0;
|
||||||
|
nsresult rv =
|
||||||
|
nsContentEventHandler::GetFlatTextOffsetOfRange(mRootContent, aContainer,
|
||||||
|
aStartIndex, &offset);
|
||||||
|
NS_ENSURE_SUCCESS_VOID(rv);
|
||||||
|
|
||||||
|
// get offset at the end of the last added node
|
||||||
|
nsIContent* childAtStart = aContainer->GetChildAt(aStartIndex);
|
||||||
|
uint32_t addingLength = 0;
|
||||||
|
rv =
|
||||||
|
nsContentEventHandler::GetFlatTextOffsetOfRange(childAtStart, aContainer,
|
||||||
|
aEndIndex, &addingLength);
|
||||||
|
NS_ENSURE_SUCCESS_VOID(rv);
|
||||||
|
|
||||||
|
if (!addingLength) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsContentUtils::AddScriptRunner(
|
||||||
|
new TextChangeEvent(this, offset, offset, offset + addingLength,
|
||||||
|
causedByComposition));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IMEContentObserver::ContentAppended(nsIDocument* aDocument,
|
||||||
|
nsIContent* aContainer,
|
||||||
|
nsIContent* aFirstNewContent,
|
||||||
|
int32_t aNewIndexInContainer)
|
||||||
|
{
|
||||||
|
NotifyContentAdded(aContainer, aNewIndexInContainer,
|
||||||
|
aContainer->GetChildCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IMEContentObserver::ContentInserted(nsIDocument* aDocument,
|
||||||
|
nsIContent* aContainer,
|
||||||
|
nsIContent* aChild,
|
||||||
|
int32_t aIndexInContainer)
|
||||||
|
{
|
||||||
|
NotifyContentAdded(NODE_FROM(aContainer, aDocument),
|
||||||
|
aIndexInContainer, aIndexInContainer + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IMEContentObserver::ContentRemoved(nsIDocument* aDocument,
|
||||||
|
nsIContent* aContainer,
|
||||||
|
nsIContent* aChild,
|
||||||
|
int32_t aIndexInContainer,
|
||||||
|
nsIContent* aPreviousSibling)
|
||||||
|
{
|
||||||
|
bool causedByComposition = IsEditorHandlingEventForComposition();
|
||||||
|
if (causedByComposition &&
|
||||||
|
!mUpdatePreference.WantChangesCausedByComposition()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t offset = 0;
|
||||||
|
nsresult rv =
|
||||||
|
nsContentEventHandler::GetFlatTextOffsetOfRange(mRootContent,
|
||||||
|
NODE_FROM(aContainer,
|
||||||
|
aDocument),
|
||||||
|
aIndexInContainer, &offset);
|
||||||
|
NS_ENSURE_SUCCESS_VOID(rv);
|
||||||
|
|
||||||
|
// get offset at the end of the deleted node
|
||||||
|
int32_t nodeLength =
|
||||||
|
aChild->IsNodeOfType(nsINode::eTEXT) ?
|
||||||
|
static_cast<int32_t>(aChild->TextLength()) :
|
||||||
|
std::max(static_cast<int32_t>(aChild->GetChildCount()), 1);
|
||||||
|
MOZ_ASSERT(nodeLength >= 0, "The node length is out of range");
|
||||||
|
uint32_t textLength = 0;
|
||||||
|
rv =
|
||||||
|
nsContentEventHandler::GetFlatTextOffsetOfRange(aChild, aChild,
|
||||||
|
nodeLength, &textLength);
|
||||||
|
NS_ENSURE_SUCCESS_VOID(rv);
|
||||||
|
|
||||||
|
if (!textLength) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsContentUtils::AddScriptRunner(
|
||||||
|
new TextChangeEvent(this, offset, offset + textLength, offset,
|
||||||
|
causedByComposition));
|
||||||
|
}
|
||||||
|
|
||||||
|
static nsIContent*
|
||||||
|
GetContentBR(dom::Element* aElement)
|
||||||
|
{
|
||||||
|
if (!aElement->IsNodeOfType(nsINode::eCONTENT)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
nsIContent* content = static_cast<nsIContent*>(aElement);
|
||||||
|
return content->IsHTML(nsGkAtoms::br) ? content : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IMEContentObserver::AttributeWillChange(nsIDocument* aDocument,
|
||||||
|
dom::Element* aElement,
|
||||||
|
int32_t aNameSpaceID,
|
||||||
|
nsIAtom* aAttribute,
|
||||||
|
int32_t aModType)
|
||||||
|
{
|
||||||
|
nsIContent *content = GetContentBR(aElement);
|
||||||
|
mPreAttrChangeLength = content ?
|
||||||
|
nsContentEventHandler::GetNativeTextLength(content) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IMEContentObserver::AttributeChanged(nsIDocument* aDocument,
|
||||||
|
dom::Element* aElement,
|
||||||
|
int32_t aNameSpaceID,
|
||||||
|
nsIAtom* aAttribute,
|
||||||
|
int32_t aModType)
|
||||||
|
{
|
||||||
|
bool causedByComposition = IsEditorHandlingEventForComposition();
|
||||||
|
if (causedByComposition &&
|
||||||
|
!mUpdatePreference.WantChangesCausedByComposition()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIContent *content = GetContentBR(aElement);
|
||||||
|
if (!content) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t postAttrChangeLength =
|
||||||
|
nsContentEventHandler::GetNativeTextLength(content);
|
||||||
|
if (postAttrChangeLength == mPreAttrChangeLength) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint32_t start;
|
||||||
|
nsresult rv =
|
||||||
|
nsContentEventHandler::GetFlatTextOffsetOfRange(mRootContent, content,
|
||||||
|
0, &start);
|
||||||
|
NS_ENSURE_SUCCESS_VOID(rv);
|
||||||
|
|
||||||
|
nsContentUtils::AddScriptRunner(
|
||||||
|
new TextChangeEvent(this, start, start + mPreAttrChangeLength,
|
||||||
|
start + postAttrChangeLength, causedByComposition));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mozilla
|
|
@ -0,0 +1,79 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=2 sw=2 et tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef mozilla_IMEContentObserver_h_
|
||||||
|
#define mozilla_IMEContentObserver_h_
|
||||||
|
|
||||||
|
#include "mozilla/Attributes.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
#include "nsIDocShell.h" // XXX Why does only this need to be included here?
|
||||||
|
#include "nsIReflowObserver.h"
|
||||||
|
#include "nsISelectionListener.h"
|
||||||
|
#include "nsIScrollObserver.h"
|
||||||
|
#include "nsIWidget.h" // for nsIMEUpdatePreference
|
||||||
|
#include "nsStubMutationObserver.h"
|
||||||
|
#include "nsWeakReference.h"
|
||||||
|
|
||||||
|
class nsIContent;
|
||||||
|
class nsINode;
|
||||||
|
class nsISelection;
|
||||||
|
class nsPresContext;
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
// IMEContentObserver notifies widget of any text and selection changes
|
||||||
|
// in the currently focused editor
|
||||||
|
class IMEContentObserver MOZ_FINAL : public nsISelectionListener,
|
||||||
|
public nsStubMutationObserver,
|
||||||
|
public nsIReflowObserver,
|
||||||
|
public nsIScrollObserver,
|
||||||
|
public nsSupportsWeakReference
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IMEContentObserver();
|
||||||
|
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
NS_DECL_NSISELECTIONLISTENER
|
||||||
|
NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
|
||||||
|
NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
|
||||||
|
NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
|
||||||
|
NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
|
||||||
|
NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTEWILLCHANGE
|
||||||
|
NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
|
||||||
|
NS_DECL_NSIREFLOWOBSERVER
|
||||||
|
|
||||||
|
// nsIScrollObserver
|
||||||
|
virtual void ScrollPositionChanged() MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
void Init(nsIWidget* aWidget, nsPresContext* aPresContext,
|
||||||
|
nsIContent* aContent);
|
||||||
|
void Destroy();
|
||||||
|
bool IsManaging(nsPresContext* aPresContext, nsIContent* aContent);
|
||||||
|
bool IsEditorHandlingEventForComposition() const;
|
||||||
|
bool KeepAliveDuringDeactive() const
|
||||||
|
{
|
||||||
|
return mUpdatePreference.WantDuringDeactive();
|
||||||
|
}
|
||||||
|
nsIWidget* GetWidget() const { return mWidget; }
|
||||||
|
nsresult GetSelectionAndRoot(nsISelection** aSelection,
|
||||||
|
nsIContent** aRoot) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void NotifyContentAdded(nsINode* aContainer, int32_t aStart, int32_t aEnd);
|
||||||
|
void ObserveEditableNode();
|
||||||
|
|
||||||
|
nsCOMPtr<nsIWidget> mWidget;
|
||||||
|
nsCOMPtr<nsISelection> mSelection;
|
||||||
|
nsCOMPtr<nsIContent> mRootContent;
|
||||||
|
nsCOMPtr<nsINode> mEditableNode;
|
||||||
|
nsCOMPtr<nsIDocShell> mDocShell;
|
||||||
|
nsIMEUpdatePreference mUpdatePreference;
|
||||||
|
uint32_t mPreAttrChangeLength;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // mozilla_IMEContentObserver_h_
|
|
@ -0,0 +1,775 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=2 sw=2 et tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "mozilla/IMEStateManager.h"
|
||||||
|
|
||||||
|
#include "mozilla/Attributes.h"
|
||||||
|
#include "mozilla/Preferences.h"
|
||||||
|
#include "mozilla/Services.h"
|
||||||
|
#include "mozilla/TextEvents.h"
|
||||||
|
#include "mozilla/dom/HTMLFormElement.h"
|
||||||
|
|
||||||
|
#include "HTMLInputElement.h"
|
||||||
|
#include "IMEContentObserver.h"
|
||||||
|
#include "TextComposition.h"
|
||||||
|
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
#include "nsContentUtils.h"
|
||||||
|
#include "nsIContent.h"
|
||||||
|
#include "nsIDocument.h"
|
||||||
|
#include "nsIDOMMouseEvent.h"
|
||||||
|
#include "nsIForm.h"
|
||||||
|
#include "nsIFormControl.h"
|
||||||
|
#include "nsINode.h"
|
||||||
|
#include "nsIObserverService.h"
|
||||||
|
#include "nsIPresShell.h"
|
||||||
|
#include "nsISelection.h"
|
||||||
|
#include "nsISupports.h"
|
||||||
|
#include "nsPresContext.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
|
||||||
|
using namespace dom;
|
||||||
|
using namespace widget;
|
||||||
|
|
||||||
|
nsIContent* IMEStateManager::sContent = nullptr;
|
||||||
|
nsPresContext* IMEStateManager::sPresContext = nullptr;
|
||||||
|
bool IMEStateManager::sInstalledMenuKeyboardListener = false;
|
||||||
|
bool IMEStateManager::sIsTestingIME = false;
|
||||||
|
|
||||||
|
// sActiveIMEContentObserver points to the currently active IMEContentObserver.
|
||||||
|
// sActiveIMEContentObserver is null if there is no focused editor.
|
||||||
|
IMEContentObserver* IMEStateManager::sActiveIMEContentObserver = nullptr;
|
||||||
|
TextCompositionArray* IMEStateManager::sTextCompositions = nullptr;
|
||||||
|
|
||||||
|
void
|
||||||
|
IMEStateManager::Shutdown()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(!sTextCompositions || !sTextCompositions->Length());
|
||||||
|
delete sTextCompositions;
|
||||||
|
sTextCompositions = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
IMEStateManager::OnDestroyPresContext(nsPresContext* aPresContext)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aPresContext);
|
||||||
|
|
||||||
|
// First, if there is a composition in the aPresContext, clean up it.
|
||||||
|
if (sTextCompositions) {
|
||||||
|
TextCompositionArray::index_type i =
|
||||||
|
sTextCompositions->IndexOf(aPresContext);
|
||||||
|
if (i != TextCompositionArray::NoIndex) {
|
||||||
|
// there should be only one composition per presContext object.
|
||||||
|
sTextCompositions->ElementAt(i)->Destroy();
|
||||||
|
sTextCompositions->RemoveElementAt(i);
|
||||||
|
MOZ_ASSERT(sTextCompositions->IndexOf(aPresContext) ==
|
||||||
|
TextCompositionArray::NoIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aPresContext != sPresContext) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
DestroyTextStateManager();
|
||||||
|
|
||||||
|
nsCOMPtr<nsIWidget> widget = sPresContext->GetRootWidget();
|
||||||
|
if (widget) {
|
||||||
|
IMEState newState = GetNewIMEState(sPresContext, nullptr);
|
||||||
|
InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
|
||||||
|
InputContextAction::LOST_FOCUS);
|
||||||
|
SetIMEState(newState, nullptr, widget, action);
|
||||||
|
}
|
||||||
|
NS_IF_RELEASE(sContent);
|
||||||
|
sPresContext = nullptr;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
IMEStateManager::OnRemoveContent(nsPresContext* aPresContext,
|
||||||
|
nsIContent* aContent)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG_POINTER(aPresContext);
|
||||||
|
|
||||||
|
// First, if there is a composition in the aContent, clean up it.
|
||||||
|
if (sTextCompositions) {
|
||||||
|
nsRefPtr<TextComposition> compositionInContent =
|
||||||
|
sTextCompositions->GetCompositionInContent(aPresContext, aContent);
|
||||||
|
|
||||||
|
if (compositionInContent) {
|
||||||
|
// Try resetting the native IME state. Be aware, typically, this method
|
||||||
|
// is called during the content being removed. Then, the native
|
||||||
|
// composition events which are caused by following APIs are ignored due
|
||||||
|
// to unsafe to run script (in PresShell::HandleEvent()).
|
||||||
|
nsCOMPtr<nsIWidget> widget = aPresContext->GetRootWidget();
|
||||||
|
if (widget) {
|
||||||
|
nsresult rv =
|
||||||
|
compositionInContent->NotifyIME(REQUEST_TO_CANCEL_COMPOSITION);
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
compositionInContent->NotifyIME(REQUEST_TO_COMMIT_COMPOSITION);
|
||||||
|
}
|
||||||
|
// By calling the APIs, the composition may have been finished normally.
|
||||||
|
compositionInContent =
|
||||||
|
sTextCompositions->GetCompositionFor(
|
||||||
|
compositionInContent->GetPresContext(),
|
||||||
|
compositionInContent->GetEventTargetNode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the compositionInContent is still available, we should finish the
|
||||||
|
// composition just on the content forcibly.
|
||||||
|
if (compositionInContent) {
|
||||||
|
compositionInContent->SynthesizeCommit(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sPresContext || !sContent ||
|
||||||
|
!nsContentUtils::ContentIsDescendantOf(sContent, aContent)) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
DestroyTextStateManager();
|
||||||
|
|
||||||
|
// Current IME transaction should commit
|
||||||
|
nsCOMPtr<nsIWidget> widget = sPresContext->GetRootWidget();
|
||||||
|
if (widget) {
|
||||||
|
IMEState newState = GetNewIMEState(sPresContext, nullptr);
|
||||||
|
InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
|
||||||
|
InputContextAction::LOST_FOCUS);
|
||||||
|
SetIMEState(newState, nullptr, widget, action);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IF_RELEASE(sContent);
|
||||||
|
sPresContext = nullptr;
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
IMEStateManager::OnChangeFocus(nsPresContext* aPresContext,
|
||||||
|
nsIContent* aContent,
|
||||||
|
InputContextAction::Cause aCause)
|
||||||
|
{
|
||||||
|
InputContextAction action(aCause);
|
||||||
|
return OnChangeFocusInternal(aPresContext, aContent, action);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
IMEStateManager::OnChangeFocusInternal(nsPresContext* aPresContext,
|
||||||
|
nsIContent* aContent,
|
||||||
|
InputContextAction aAction)
|
||||||
|
{
|
||||||
|
bool focusActuallyChanging =
|
||||||
|
(sContent != aContent || sPresContext != aPresContext);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIWidget> oldWidget =
|
||||||
|
sPresContext ? sPresContext->GetRootWidget() : nullptr;
|
||||||
|
if (oldWidget && focusActuallyChanging) {
|
||||||
|
// If we're deactivating, we shouldn't commit composition forcibly because
|
||||||
|
// the user may want to continue the composition.
|
||||||
|
if (aPresContext) {
|
||||||
|
NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, oldWidget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sActiveIMEContentObserver &&
|
||||||
|
(aPresContext || !sActiveIMEContentObserver->KeepAliveDuringDeactive()) &&
|
||||||
|
!sActiveIMEContentObserver->IsManaging(aPresContext, aContent)) {
|
||||||
|
DestroyTextStateManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!aPresContext) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIWidget> widget =
|
||||||
|
(sPresContext == aPresContext) ? oldWidget.get() :
|
||||||
|
aPresContext->GetRootWidget();
|
||||||
|
if (!widget) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
IMEState newState = GetNewIMEState(aPresContext, aContent);
|
||||||
|
if (!focusActuallyChanging) {
|
||||||
|
// actual focus isn't changing, but if IME enabled state is changing,
|
||||||
|
// we should do it.
|
||||||
|
InputContext context = widget->GetInputContext();
|
||||||
|
if (context.mIMEState.mEnabled == newState.mEnabled) {
|
||||||
|
// the enabled state isn't changing.
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
aAction.mFocusChange = InputContextAction::FOCUS_NOT_CHANGED;
|
||||||
|
|
||||||
|
// Even if focus isn't changing actually, we should commit current
|
||||||
|
// composition here since the IME state is changing.
|
||||||
|
if (sPresContext && oldWidget && !focusActuallyChanging) {
|
||||||
|
NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, oldWidget);
|
||||||
|
}
|
||||||
|
} else if (aAction.mFocusChange == InputContextAction::FOCUS_NOT_CHANGED) {
|
||||||
|
// If aContent isn't null or aContent is null but editable, somebody gets
|
||||||
|
// focus.
|
||||||
|
bool gotFocus = aContent || (newState.mEnabled == IMEState::ENABLED);
|
||||||
|
aAction.mFocusChange =
|
||||||
|
gotFocus ? InputContextAction::GOT_FOCUS : InputContextAction::LOST_FOCUS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update IME state for new focus widget
|
||||||
|
SetIMEState(newState, aContent, widget, aAction);
|
||||||
|
|
||||||
|
sPresContext = aPresContext;
|
||||||
|
if (sContent != aContent) {
|
||||||
|
NS_IF_RELEASE(sContent);
|
||||||
|
NS_IF_ADDREF(sContent = aContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't call CreateIMEContentObserver() here, it should be called from
|
||||||
|
// focus event handler of editor.
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IMEStateManager::OnInstalledMenuKeyboardListener(bool aInstalling)
|
||||||
|
{
|
||||||
|
sInstalledMenuKeyboardListener = aInstalling;
|
||||||
|
|
||||||
|
InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
|
||||||
|
aInstalling ? InputContextAction::MENU_GOT_PSEUDO_FOCUS :
|
||||||
|
InputContextAction::MENU_LOST_PSEUDO_FOCUS);
|
||||||
|
OnChangeFocusInternal(sPresContext, sContent, action);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IMEStateManager::OnClickInEditor(nsPresContext* aPresContext,
|
||||||
|
nsIContent* aContent,
|
||||||
|
nsIDOMMouseEvent* aMouseEvent)
|
||||||
|
{
|
||||||
|
if (sPresContext != aPresContext || sContent != aContent) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIWidget> widget = aPresContext->GetRootWidget();
|
||||||
|
NS_ENSURE_TRUE_VOID(widget);
|
||||||
|
|
||||||
|
bool isTrusted;
|
||||||
|
nsresult rv = aMouseEvent->GetIsTrusted(&isTrusted);
|
||||||
|
NS_ENSURE_SUCCESS_VOID(rv);
|
||||||
|
if (!isTrusted) {
|
||||||
|
return; // ignore untrusted event.
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t button;
|
||||||
|
rv = aMouseEvent->GetButton(&button);
|
||||||
|
NS_ENSURE_SUCCESS_VOID(rv);
|
||||||
|
if (button != 0) {
|
||||||
|
return; // not a left click event.
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t clickCount;
|
||||||
|
rv = aMouseEvent->GetDetail(&clickCount);
|
||||||
|
NS_ENSURE_SUCCESS_VOID(rv);
|
||||||
|
if (clickCount != 1) {
|
||||||
|
return; // should notify only first click event.
|
||||||
|
}
|
||||||
|
|
||||||
|
InputContextAction action(InputContextAction::CAUSE_MOUSE,
|
||||||
|
InputContextAction::FOCUS_NOT_CHANGED);
|
||||||
|
IMEState newState = GetNewIMEState(aPresContext, aContent);
|
||||||
|
SetIMEState(newState, aContent, widget, action);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IMEStateManager::OnFocusInEditor(nsPresContext* aPresContext,
|
||||||
|
nsIContent* aContent)
|
||||||
|
{
|
||||||
|
if (sPresContext != aPresContext || sContent != aContent) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the IMEContentObserver instance isn't managing the editor actually,
|
||||||
|
// we need to recreate the instance.
|
||||||
|
if (sActiveIMEContentObserver) {
|
||||||
|
if (sActiveIMEContentObserver->IsManaging(aPresContext, aContent)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DestroyTextStateManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
CreateIMEContentObserver();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IMEStateManager::UpdateIMEState(const IMEState& aNewIMEState,
|
||||||
|
nsIContent* aContent)
|
||||||
|
{
|
||||||
|
if (!sPresContext) {
|
||||||
|
NS_WARNING("ISM doesn't know which editor has focus");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
nsCOMPtr<nsIWidget> widget = sPresContext->GetRootWidget();
|
||||||
|
if (!widget) {
|
||||||
|
NS_WARNING("focused widget is not found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the IMEContentObserver instance isn't managing the editor's current
|
||||||
|
// editable root content, the editor frame might be reframed. We should
|
||||||
|
// recreate the instance at that time.
|
||||||
|
bool createTextStateManager =
|
||||||
|
(!sActiveIMEContentObserver ||
|
||||||
|
!sActiveIMEContentObserver->IsManaging(sPresContext, aContent));
|
||||||
|
|
||||||
|
bool updateIMEState =
|
||||||
|
(widget->GetInputContext().mIMEState.mEnabled != aNewIMEState.mEnabled);
|
||||||
|
|
||||||
|
if (updateIMEState) {
|
||||||
|
// commit current composition before modifying IME state.
|
||||||
|
NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (createTextStateManager) {
|
||||||
|
DestroyTextStateManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateIMEState) {
|
||||||
|
InputContextAction action(InputContextAction::CAUSE_UNKNOWN,
|
||||||
|
InputContextAction::FOCUS_NOT_CHANGED);
|
||||||
|
SetIMEState(aNewIMEState, aContent, widget, action);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (createTextStateManager) {
|
||||||
|
CreateIMEContentObserver();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IMEState
|
||||||
|
IMEStateManager::GetNewIMEState(nsPresContext* aPresContext,
|
||||||
|
nsIContent* aContent)
|
||||||
|
{
|
||||||
|
// On Printing or Print Preview, we don't need IME.
|
||||||
|
if (aPresContext->Type() == nsPresContext::eContext_PrintPreview ||
|
||||||
|
aPresContext->Type() == nsPresContext::eContext_Print) {
|
||||||
|
return IMEState(IMEState::DISABLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sInstalledMenuKeyboardListener) {
|
||||||
|
return IMEState(IMEState::DISABLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!aContent) {
|
||||||
|
// Even if there are no focused content, the focused document might be
|
||||||
|
// editable, such case is design mode.
|
||||||
|
nsIDocument* doc = aPresContext->Document();
|
||||||
|
if (doc && doc->HasFlag(NODE_IS_EDITABLE)) {
|
||||||
|
return IMEState(IMEState::ENABLED);
|
||||||
|
}
|
||||||
|
return IMEState(IMEState::DISABLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
return aContent->GetDesiredIMEState();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper class, used for IME enabled state change notification
|
||||||
|
class IMEEnabledStateChangedEvent : public nsRunnable {
|
||||||
|
public:
|
||||||
|
IMEEnabledStateChangedEvent(uint32_t aState)
|
||||||
|
: mState(aState)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHOD Run()
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsIObserverService> observerService =
|
||||||
|
services::GetObserverService();
|
||||||
|
if (observerService) {
|
||||||
|
nsAutoString state;
|
||||||
|
state.AppendInt(mState);
|
||||||
|
observerService->NotifyObservers(nullptr, "ime-enabled-state-changed",
|
||||||
|
state.get());
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32_t mState;
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
IMEStateManager::SetIMEState(const IMEState& aState,
|
||||||
|
nsIContent* aContent,
|
||||||
|
nsIWidget* aWidget,
|
||||||
|
InputContextAction aAction)
|
||||||
|
{
|
||||||
|
NS_ENSURE_TRUE_VOID(aWidget);
|
||||||
|
|
||||||
|
InputContext oldContext = aWidget->GetInputContext();
|
||||||
|
|
||||||
|
InputContext context;
|
||||||
|
context.mIMEState = aState;
|
||||||
|
|
||||||
|
if (aContent && aContent->GetNameSpaceID() == kNameSpaceID_XHTML &&
|
||||||
|
(aContent->Tag() == nsGkAtoms::input ||
|
||||||
|
aContent->Tag() == nsGkAtoms::textarea)) {
|
||||||
|
if (aContent->Tag() != nsGkAtoms::textarea) {
|
||||||
|
// <input type=number> has an anonymous <input type=text> descendant
|
||||||
|
// that gets focus whenever anyone tries to focus the number control. We
|
||||||
|
// need to check if aContent is one of those anonymous text controls and,
|
||||||
|
// if so, use the number control instead:
|
||||||
|
nsIContent* content = aContent;
|
||||||
|
HTMLInputElement* inputElement =
|
||||||
|
HTMLInputElement::FromContentOrNull(aContent);
|
||||||
|
if (inputElement) {
|
||||||
|
HTMLInputElement* ownerNumberControl =
|
||||||
|
inputElement->GetOwnerNumberControl();
|
||||||
|
if (ownerNumberControl) {
|
||||||
|
content = ownerNumberControl; // an <input type=number>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
content->GetAttr(kNameSpaceID_None, nsGkAtoms::type,
|
||||||
|
context.mHTMLInputType);
|
||||||
|
} else {
|
||||||
|
context.mHTMLInputType.Assign(nsGkAtoms::textarea->GetUTF16String());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Preferences::GetBool("dom.forms.inputmode", false)) {
|
||||||
|
aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::inputmode,
|
||||||
|
context.mHTMLInputInputmode);
|
||||||
|
}
|
||||||
|
|
||||||
|
aContent->GetAttr(kNameSpaceID_None, nsGkAtoms::moz_action_hint,
|
||||||
|
context.mActionHint);
|
||||||
|
|
||||||
|
// if we don't have an action hint and return won't submit the form use "next"
|
||||||
|
if (context.mActionHint.IsEmpty() && aContent->Tag() == nsGkAtoms::input) {
|
||||||
|
bool willSubmit = false;
|
||||||
|
nsCOMPtr<nsIFormControl> control(do_QueryInterface(aContent));
|
||||||
|
mozilla::dom::Element* formElement = control->GetFormElement();
|
||||||
|
nsCOMPtr<nsIForm> form;
|
||||||
|
if (control) {
|
||||||
|
// is this a form and does it have a default submit element?
|
||||||
|
if ((form = do_QueryInterface(formElement)) &&
|
||||||
|
form->GetDefaultSubmitElement()) {
|
||||||
|
willSubmit = true;
|
||||||
|
// is this an html form and does it only have a single text input element?
|
||||||
|
} else if (formElement && formElement->Tag() == nsGkAtoms::form &&
|
||||||
|
formElement->IsHTML() &&
|
||||||
|
!static_cast<dom::HTMLFormElement*>(formElement)->
|
||||||
|
ImplicitSubmissionIsDisabled()) {
|
||||||
|
willSubmit = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
context.mActionHint.Assign(
|
||||||
|
willSubmit ? (control->GetType() == NS_FORM_INPUT_SEARCH ?
|
||||||
|
NS_LITERAL_STRING("search") : NS_LITERAL_STRING("go")) :
|
||||||
|
(formElement ?
|
||||||
|
NS_LITERAL_STRING("next") : EmptyString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX I think that we should use nsContentUtils::IsCallerChrome() instead
|
||||||
|
// of the process type.
|
||||||
|
if (aAction.mCause == InputContextAction::CAUSE_UNKNOWN &&
|
||||||
|
XRE_GetProcessType() != GeckoProcessType_Content) {
|
||||||
|
aAction.mCause = InputContextAction::CAUSE_UNKNOWN_CHROME;
|
||||||
|
}
|
||||||
|
|
||||||
|
aWidget->SetInputContext(context, aAction);
|
||||||
|
if (oldContext.mIMEState.mEnabled == context.mIMEState.mEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsContentUtils::AddScriptRunner(
|
||||||
|
new IMEEnabledStateChangedEvent(context.mIMEState.mEnabled));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IMEStateManager::EnsureTextCompositionArray()
|
||||||
|
{
|
||||||
|
if (sTextCompositions) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sTextCompositions = new TextCompositionArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IMEStateManager::DispatchCompositionEvent(nsINode* aEventTargetNode,
|
||||||
|
nsPresContext* aPresContext,
|
||||||
|
WidgetEvent* aEvent,
|
||||||
|
nsEventStatus* aStatus,
|
||||||
|
nsDispatchingCallback* aCallBack)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aEvent->eventStructType == NS_COMPOSITION_EVENT ||
|
||||||
|
aEvent->eventStructType == NS_TEXT_EVENT);
|
||||||
|
if (!aEvent->mFlags.mIsTrusted || aEvent->mFlags.mPropagationStopped) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
EnsureTextCompositionArray();
|
||||||
|
|
||||||
|
WidgetGUIEvent* GUIEvent = aEvent->AsGUIEvent();
|
||||||
|
|
||||||
|
nsRefPtr<TextComposition> composition =
|
||||||
|
sTextCompositions->GetCompositionFor(GUIEvent->widget);
|
||||||
|
if (!composition) {
|
||||||
|
MOZ_ASSERT(GUIEvent->message == NS_COMPOSITION_START);
|
||||||
|
composition = new TextComposition(aPresContext, aEventTargetNode, GUIEvent);
|
||||||
|
sTextCompositions->AppendElement(composition);
|
||||||
|
}
|
||||||
|
#ifdef DEBUG
|
||||||
|
else {
|
||||||
|
MOZ_ASSERT(GUIEvent->message != NS_COMPOSITION_START);
|
||||||
|
}
|
||||||
|
#endif // #ifdef DEBUG
|
||||||
|
|
||||||
|
// Dispatch the event on composing target.
|
||||||
|
composition->DispatchEvent(GUIEvent, aStatus, aCallBack);
|
||||||
|
|
||||||
|
// WARNING: the |composition| might have been destroyed already.
|
||||||
|
|
||||||
|
// Remove the ended composition from the array.
|
||||||
|
if (aEvent->message == NS_COMPOSITION_END) {
|
||||||
|
TextCompositionArray::index_type i =
|
||||||
|
sTextCompositions->IndexOf(GUIEvent->widget);
|
||||||
|
if (i != TextCompositionArray::NoIndex) {
|
||||||
|
sTextCompositions->ElementAt(i)->Destroy();
|
||||||
|
sTextCompositions->RemoveElementAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
nsresult
|
||||||
|
IMEStateManager::NotifyIME(IMEMessage aMessage,
|
||||||
|
nsIWidget* aWidget)
|
||||||
|
{
|
||||||
|
NS_ENSURE_TRUE(aWidget, NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
|
nsRefPtr<TextComposition> composition;
|
||||||
|
if (sTextCompositions) {
|
||||||
|
composition = sTextCompositions->GetCompositionFor(aWidget);
|
||||||
|
}
|
||||||
|
if (!composition || !composition->IsSynthesizedForTests()) {
|
||||||
|
switch (aMessage) {
|
||||||
|
case NOTIFY_IME_OF_CURSOR_POS_CHANGED:
|
||||||
|
return aWidget->NotifyIME(IMENotification(aMessage));
|
||||||
|
case REQUEST_TO_COMMIT_COMPOSITION:
|
||||||
|
case REQUEST_TO_CANCEL_COMPOSITION:
|
||||||
|
case NOTIFY_IME_OF_COMPOSITION_UPDATE:
|
||||||
|
return composition ?
|
||||||
|
aWidget->NotifyIME(IMENotification(aMessage)) : NS_OK;
|
||||||
|
default:
|
||||||
|
MOZ_CRASH("Unsupported notification");
|
||||||
|
}
|
||||||
|
MOZ_CRASH(
|
||||||
|
"Failed to handle the notification for non-synthesized composition");
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the composition is synthesized events for automated tests, we should
|
||||||
|
// dispatch composition events for emulating the native composition behavior.
|
||||||
|
// NOTE: The dispatched events are discarded if it's not safe to run script.
|
||||||
|
switch (aMessage) {
|
||||||
|
case REQUEST_TO_COMMIT_COMPOSITION: {
|
||||||
|
nsCOMPtr<nsIWidget> widget(aWidget);
|
||||||
|
nsEventStatus status = nsEventStatus_eIgnore;
|
||||||
|
if (!composition->LastData().IsEmpty()) {
|
||||||
|
WidgetTextEvent textEvent(true, NS_TEXT_TEXT, widget);
|
||||||
|
textEvent.theText = composition->LastData();
|
||||||
|
textEvent.mFlags.mIsSynthesizedForTests = true;
|
||||||
|
widget->DispatchEvent(&textEvent, status);
|
||||||
|
if (widget->Destroyed()) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
status = nsEventStatus_eIgnore;
|
||||||
|
WidgetCompositionEvent endEvent(true, NS_COMPOSITION_END, widget);
|
||||||
|
endEvent.data = composition->LastData();
|
||||||
|
endEvent.mFlags.mIsSynthesizedForTests = true;
|
||||||
|
widget->DispatchEvent(&endEvent, status);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
case REQUEST_TO_CANCEL_COMPOSITION: {
|
||||||
|
nsCOMPtr<nsIWidget> widget(aWidget);
|
||||||
|
nsEventStatus status = nsEventStatus_eIgnore;
|
||||||
|
if (!composition->LastData().IsEmpty()) {
|
||||||
|
WidgetCompositionEvent updateEvent(true, NS_COMPOSITION_UPDATE, widget);
|
||||||
|
updateEvent.data = composition->LastData();
|
||||||
|
updateEvent.mFlags.mIsSynthesizedForTests = true;
|
||||||
|
widget->DispatchEvent(&updateEvent, status);
|
||||||
|
if (widget->Destroyed()) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
status = nsEventStatus_eIgnore;
|
||||||
|
WidgetTextEvent textEvent(true, NS_TEXT_TEXT, widget);
|
||||||
|
textEvent.theText = composition->LastData();
|
||||||
|
textEvent.mFlags.mIsSynthesizedForTests = true;
|
||||||
|
widget->DispatchEvent(&textEvent, status);
|
||||||
|
if (widget->Destroyed()) {
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
status = nsEventStatus_eIgnore;
|
||||||
|
WidgetCompositionEvent endEvent(true, NS_COMPOSITION_END, widget);
|
||||||
|
endEvent.data = composition->LastData();
|
||||||
|
endEvent.mFlags.mIsSynthesizedForTests = true;
|
||||||
|
widget->DispatchEvent(&endEvent, status);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
nsresult
|
||||||
|
IMEStateManager::NotifyIME(IMEMessage aMessage,
|
||||||
|
nsPresContext* aPresContext)
|
||||||
|
{
|
||||||
|
NS_ENSURE_TRUE(aPresContext, NS_ERROR_INVALID_ARG);
|
||||||
|
|
||||||
|
nsIWidget* widget = aPresContext->GetRootWidget();
|
||||||
|
if (!widget) {
|
||||||
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
|
}
|
||||||
|
return NotifyIME(aMessage, widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
IMEStateManager::IsEditable(nsINode* node)
|
||||||
|
{
|
||||||
|
if (node->IsEditable()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// |node| might be readwrite (for example, a text control)
|
||||||
|
if (node->IsElement() &&
|
||||||
|
node->AsElement()->State().HasState(NS_EVENT_STATE_MOZ_READWRITE)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsINode*
|
||||||
|
IMEStateManager::GetRootEditableNode(nsPresContext* aPresContext,
|
||||||
|
nsIContent* aContent)
|
||||||
|
{
|
||||||
|
if (aContent) {
|
||||||
|
nsINode* root = nullptr;
|
||||||
|
nsINode* node = aContent;
|
||||||
|
while (node && IsEditable(node)) {
|
||||||
|
root = node;
|
||||||
|
node = node->GetParentNode();
|
||||||
|
}
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
if (aPresContext) {
|
||||||
|
nsIDocument* document = aPresContext->Document();
|
||||||
|
if (document && document->IsEditable()) {
|
||||||
|
return document;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
IMEStateManager::IsEditableIMEState(nsIWidget* aWidget)
|
||||||
|
{
|
||||||
|
switch (aWidget->GetInputContext().mIMEState.mEnabled) {
|
||||||
|
case IMEState::ENABLED:
|
||||||
|
case IMEState::PASSWORD:
|
||||||
|
return true;
|
||||||
|
case IMEState::PLUGIN:
|
||||||
|
case IMEState::DISABLED:
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
MOZ_CRASH("Unknown IME enable state");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IMEStateManager::DestroyTextStateManager()
|
||||||
|
{
|
||||||
|
if (!sActiveIMEContentObserver) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsRefPtr<IMEContentObserver> tsm;
|
||||||
|
tsm.swap(sActiveIMEContentObserver);
|
||||||
|
tsm->Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
IMEStateManager::CreateIMEContentObserver()
|
||||||
|
{
|
||||||
|
if (sActiveIMEContentObserver) {
|
||||||
|
NS_WARNING("text state observer has been there already");
|
||||||
|
MOZ_ASSERT(sActiveIMEContentObserver->IsManaging(sPresContext, sContent));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsCOMPtr<nsIWidget> widget = sPresContext->GetRootWidget();
|
||||||
|
if (!widget) {
|
||||||
|
return; // Sometimes, there are no widgets.
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it's not text ediable, we don't need to create IMEContentObserver.
|
||||||
|
if (!IsEditableIMEState(widget)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool sInitializeIsTestingIME = true;
|
||||||
|
if (sInitializeIsTestingIME) {
|
||||||
|
Preferences::AddBoolVarCache(&sIsTestingIME, "test.IME", false);
|
||||||
|
sInitializeIsTestingIME = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sActiveIMEContentObserver = new IMEContentObserver();
|
||||||
|
NS_ADDREF(sActiveIMEContentObserver);
|
||||||
|
|
||||||
|
// IMEContentObserver::Init() might create another IMEContentObserver
|
||||||
|
// instance. So, sActiveIMEContentObserver would be replaced with new one.
|
||||||
|
// We should hold the current instance here.
|
||||||
|
nsRefPtr<IMEContentObserver> kungFuDeathGrip(sActiveIMEContentObserver);
|
||||||
|
sActiveIMEContentObserver->Init(widget, sPresContext, sContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
IMEStateManager::GetFocusSelectionAndRoot(nsISelection** aSelection,
|
||||||
|
nsIContent** aRootContent)
|
||||||
|
{
|
||||||
|
if (!sActiveIMEContentObserver) {
|
||||||
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
|
}
|
||||||
|
return sActiveIMEContentObserver->GetSelectionAndRoot(aSelection,
|
||||||
|
aRootContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
already_AddRefed<TextComposition>
|
||||||
|
IMEStateManager::GetTextCompositionFor(nsIWidget* aWidget)
|
||||||
|
{
|
||||||
|
if (!sTextCompositions) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
nsRefPtr<TextComposition> textComposition =
|
||||||
|
sTextCompositions->GetCompositionFor(aWidget);
|
||||||
|
return textComposition.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
already_AddRefed<TextComposition>
|
||||||
|
IMEStateManager::GetTextCompositionFor(WidgetGUIEvent* aEvent)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(aEvent->AsCompositionEvent() || aEvent->AsTextEvent(),
|
||||||
|
"aEvent has to be WidgetCompositionEvent or WidgetTextEvent");
|
||||||
|
return GetTextCompositionFor(aEvent->widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mozilla
|
|
@ -3,8 +3,8 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#ifndef nsIMEStateManager_h__
|
#ifndef mozilla_IMEStateManager_h_
|
||||||
#define nsIMEStateManager_h__
|
#define mozilla_IMEStateManager_h_
|
||||||
|
|
||||||
#include "mozilla/EventForwards.h"
|
#include "mozilla/EventForwards.h"
|
||||||
#include "nsIWidget.h"
|
#include "nsIWidget.h"
|
||||||
|
@ -15,26 +15,26 @@ class nsIDOMMouseEvent;
|
||||||
class nsINode;
|
class nsINode;
|
||||||
class nsPIDOMWindow;
|
class nsPIDOMWindow;
|
||||||
class nsPresContext;
|
class nsPresContext;
|
||||||
class nsTextStateManager;
|
|
||||||
class nsISelection;
|
class nsISelection;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
|
class IMEContentObserver;
|
||||||
class TextCompositionArray;
|
class TextCompositionArray;
|
||||||
class TextComposition;
|
class TextComposition;
|
||||||
} // namespace mozilla
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* IME state manager
|
* IMEStateManager manages InputContext (e.g., active editor type, IME enabled
|
||||||
|
* state and IME open state) of nsIWidget instances, manages IMEContentObserver
|
||||||
|
* and provides useful API for IME.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class nsIMEStateManager
|
class IMEStateManager
|
||||||
{
|
{
|
||||||
friend class nsTextStateManager;
|
typedef widget::IMEMessage IMEMessage;
|
||||||
protected:
|
typedef widget::IMEState IMEState;
|
||||||
typedef mozilla::widget::IMEMessage IMEMessage;
|
typedef widget::InputContext InputContext;
|
||||||
typedef mozilla::widget::IMEState IMEState;
|
typedef widget::InputContextAction InputContextAction;
|
||||||
typedef mozilla::widget::InputContext InputContext;
|
|
||||||
typedef mozilla::widget::InputContextAction InputContextAction;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void Shutdown();
|
static void Shutdown();
|
||||||
|
@ -92,14 +92,14 @@ public:
|
||||||
*/
|
*/
|
||||||
static void DispatchCompositionEvent(nsINode* aEventTargetNode,
|
static void DispatchCompositionEvent(nsINode* aEventTargetNode,
|
||||||
nsPresContext* aPresContext,
|
nsPresContext* aPresContext,
|
||||||
mozilla::WidgetEvent* aEvent,
|
WidgetEvent* aEvent,
|
||||||
nsEventStatus* aStatus,
|
nsEventStatus* aStatus,
|
||||||
nsDispatchingCallback* aCallBack);
|
nsDispatchingCallback* aCallBack);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get TextComposition from widget.
|
* Get TextComposition from widget.
|
||||||
*/
|
*/
|
||||||
static already_AddRefed<mozilla::TextComposition>
|
static already_AddRefed<TextComposition>
|
||||||
GetTextCompositionFor(nsIWidget* aWidget);
|
GetTextCompositionFor(nsIWidget* aWidget);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -108,8 +108,8 @@ public:
|
||||||
* @param aEvent Should be a composition event or a text event which is
|
* @param aEvent Should be a composition event or a text event which is
|
||||||
* being dispatched.
|
* being dispatched.
|
||||||
*/
|
*/
|
||||||
static already_AddRefed<mozilla::TextComposition>
|
static already_AddRefed<TextComposition>
|
||||||
GetTextCompositionFor(mozilla::WidgetGUIEvent* aEvent);
|
GetTextCompositionFor(WidgetGUIEvent* aEvent);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Send a notification to IME. It depends on the IME or platform spec what
|
* Send a notification to IME. It depends on the IME or platform spec what
|
||||||
|
@ -118,6 +118,10 @@ public:
|
||||||
static nsresult NotifyIME(IMEMessage aMessage, nsIWidget* aWidget);
|
static nsresult NotifyIME(IMEMessage aMessage, nsIWidget* aWidget);
|
||||||
static nsresult NotifyIME(IMEMessage aMessage, nsPresContext* aPresContext);
|
static nsresult NotifyIME(IMEMessage aMessage, nsPresContext* aPresContext);
|
||||||
|
|
||||||
|
static nsINode* GetRootEditableNode(nsPresContext* aPresContext,
|
||||||
|
nsIContent* aContent);
|
||||||
|
static bool IsTestingIME() { return sIsTestingIME; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static nsresult OnChangeFocusInternal(nsPresContext* aPresContext,
|
static nsresult OnChangeFocusInternal(nsPresContext* aPresContext,
|
||||||
nsIContent* aContent,
|
nsIContent* aContent,
|
||||||
|
@ -130,12 +134,10 @@ protected:
|
||||||
nsIContent* aContent);
|
nsIContent* aContent);
|
||||||
|
|
||||||
static void EnsureTextCompositionArray();
|
static void EnsureTextCompositionArray();
|
||||||
static void CreateTextStateManager();
|
static void CreateIMEContentObserver();
|
||||||
static void DestroyTextStateManager();
|
static void DestroyTextStateManager();
|
||||||
|
|
||||||
static bool IsEditable(nsINode* node);
|
static bool IsEditable(nsINode* node);
|
||||||
static nsINode* GetRootEditableNode(nsPresContext* aPresContext,
|
|
||||||
nsIContent* aContent);
|
|
||||||
|
|
||||||
static bool IsEditableIMEState(nsIWidget* aWidget);
|
static bool IsEditableIMEState(nsIWidget* aWidget);
|
||||||
|
|
||||||
|
@ -144,13 +146,15 @@ protected:
|
||||||
static bool sInstalledMenuKeyboardListener;
|
static bool sInstalledMenuKeyboardListener;
|
||||||
static bool sIsTestingIME;
|
static bool sIsTestingIME;
|
||||||
|
|
||||||
static nsTextStateManager* sTextStateObserver;
|
static IMEContentObserver* sActiveIMEContentObserver;
|
||||||
|
|
||||||
// All active compositions in the process are stored by this array.
|
// All active compositions in the process are stored by this array.
|
||||||
// When you get an item of this array and use it, please be careful.
|
// When you get an item of this array and use it, please be careful.
|
||||||
// The instances in this array can be destroyed automatically if you do
|
// The instances in this array can be destroyed automatically if you do
|
||||||
// something to cause committing or canceling the composition.
|
// something to cause committing or canceling the composition.
|
||||||
static mozilla::TextCompositionArray* sTextCompositions;
|
static TextCompositionArray* sTextCompositions;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // nsIMEStateManager_h__
|
} // namespace mozilla
|
||||||
|
|
||||||
|
#endif // mozilla_IMEStateManager_h_
|
|
@ -10,9 +10,9 @@
|
||||||
#include "nsEventDispatcher.h"
|
#include "nsEventDispatcher.h"
|
||||||
#include "nsIContent.h"
|
#include "nsIContent.h"
|
||||||
#include "nsIEditor.h"
|
#include "nsIEditor.h"
|
||||||
#include "nsIMEStateManager.h"
|
|
||||||
#include "nsIPresShell.h"
|
#include "nsIPresShell.h"
|
||||||
#include "nsPresContext.h"
|
#include "nsPresContext.h"
|
||||||
|
#include "mozilla/IMEStateManager.h"
|
||||||
#include "mozilla/MiscEvents.h"
|
#include "mozilla/MiscEvents.h"
|
||||||
#include "mozilla/TextEvents.h"
|
#include "mozilla/TextEvents.h"
|
||||||
|
|
||||||
|
@ -145,7 +145,7 @@ nsresult
|
||||||
TextComposition::NotifyIME(IMEMessage aMessage)
|
TextComposition::NotifyIME(IMEMessage aMessage)
|
||||||
{
|
{
|
||||||
NS_ENSURE_TRUE(mPresContext, NS_ERROR_NOT_AVAILABLE);
|
NS_ENSURE_TRUE(mPresContext, NS_ERROR_NOT_AVAILABLE);
|
||||||
return nsIMEStateManager::NotifyIME(aMessage, mPresContext);
|
return IMEStateManager::NotifyIME(aMessage, mPresContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -231,7 +231,7 @@ TextComposition::CompositionEventDispatcher::Run()
|
||||||
handler.OnQuerySelectedText(&selectedText);
|
handler.OnQuerySelectedText(&selectedText);
|
||||||
NS_ASSERTION(selectedText.mSucceeded, "Failed to get selected text");
|
NS_ASSERTION(selectedText.mSucceeded, "Failed to get selected text");
|
||||||
compStart.data = selectedText.mReply.mString;
|
compStart.data = selectedText.mReply.mString;
|
||||||
nsIMEStateManager::DispatchCompositionEvent(mEventTarget, mPresContext,
|
IMEStateManager::DispatchCompositionEvent(mEventTarget, mPresContext,
|
||||||
&compStart, &status, nullptr);
|
&compStart, &status, nullptr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -239,14 +239,14 @@ TextComposition::CompositionEventDispatcher::Run()
|
||||||
case NS_COMPOSITION_END: {
|
case NS_COMPOSITION_END: {
|
||||||
WidgetCompositionEvent compEvent(true, mEventMessage, mWidget);
|
WidgetCompositionEvent compEvent(true, mEventMessage, mWidget);
|
||||||
compEvent.data = mData;
|
compEvent.data = mData;
|
||||||
nsIMEStateManager::DispatchCompositionEvent(mEventTarget, mPresContext,
|
IMEStateManager::DispatchCompositionEvent(mEventTarget, mPresContext,
|
||||||
&compEvent, &status, nullptr);
|
&compEvent, &status, nullptr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NS_TEXT_TEXT: {
|
case NS_TEXT_TEXT: {
|
||||||
WidgetTextEvent textEvent(true, NS_TEXT_TEXT, mWidget);
|
WidgetTextEvent textEvent(true, NS_TEXT_TEXT, mWidget);
|
||||||
textEvent.theText = mData;
|
textEvent.theText = mData;
|
||||||
nsIMEStateManager::DispatchCompositionEvent(mEventTarget, mPresContext,
|
IMEStateManager::DispatchCompositionEvent(mEventTarget, mPresContext,
|
||||||
&textEvent, &status, nullptr);
|
&textEvent, &status, nullptr);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,10 +20,11 @@
|
||||||
|
|
||||||
class nsDispatchingCallback;
|
class nsDispatchingCallback;
|
||||||
class nsIEditor;
|
class nsIEditor;
|
||||||
class nsIMEStateManager;
|
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
|
class IMEStateManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TextComposition represents a text composition. This class stores the
|
* TextComposition represents a text composition. This class stores the
|
||||||
* composition event target and its presContext. At dispatching the event via
|
* composition event target and its presContext. At dispatching the event via
|
||||||
|
@ -32,7 +33,7 @@ namespace mozilla {
|
||||||
|
|
||||||
class TextComposition MOZ_FINAL
|
class TextComposition MOZ_FINAL
|
||||||
{
|
{
|
||||||
friend class ::nsIMEStateManager;
|
friend class IMEStateManager;
|
||||||
|
|
||||||
NS_INLINE_DECL_REFCOUNTING(TextComposition)
|
NS_INLINE_DECL_REFCOUNTING(TextComposition)
|
||||||
|
|
||||||
|
@ -71,7 +72,7 @@ public:
|
||||||
bool MatchesNativeContext(nsIWidget* aWidget) const;
|
bool MatchesNativeContext(nsIWidget* aWidget) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is called when nsIMEStateManager stops managing the instance.
|
* This is called when IMEStateManager stops managing the instance.
|
||||||
*/
|
*/
|
||||||
void Destroy();
|
void Destroy();
|
||||||
|
|
||||||
|
@ -145,7 +146,7 @@ public:
|
||||||
private:
|
private:
|
||||||
// This class holds nsPresContext weak. This instance shouldn't block
|
// This class holds nsPresContext weak. This instance shouldn't block
|
||||||
// destroying it. When the presContext is being destroyed, it's notified to
|
// destroying it. When the presContext is being destroyed, it's notified to
|
||||||
// nsIMEStateManager::OnDestroyPresContext(), and then, it destroy
|
// IMEStateManager::OnDestroyPresContext(), and then, it destroy
|
||||||
// this instance.
|
// this instance.
|
||||||
nsPresContext* mPresContext;
|
nsPresContext* mPresContext;
|
||||||
nsCOMPtr<nsINode> mNode;
|
nsCOMPtr<nsINode> mNode;
|
||||||
|
@ -252,7 +253,7 @@ private:
|
||||||
* DispatchCompositionEventRunnable() dispatches a composition or text event
|
* DispatchCompositionEventRunnable() dispatches a composition or text event
|
||||||
* to the content. Be aware, if you use this method, nsPresShellEventCB
|
* to the content. Be aware, if you use this method, nsPresShellEventCB
|
||||||
* isn't used. That means that nsIFrame::HandleEvent() is never called.
|
* isn't used. That means that nsIFrame::HandleEvent() is never called.
|
||||||
* WARNING: The instance which is managed by nsIMEStateManager may be
|
* WARNING: The instance which is managed by IMEStateManager may be
|
||||||
* destroyed by this method call.
|
* destroyed by this method call.
|
||||||
*
|
*
|
||||||
* @param aEventMessage Must be one of composition event or text event.
|
* @param aEventMessage Must be one of composition event or text event.
|
||||||
|
@ -270,7 +271,7 @@ private:
|
||||||
* Managing with array is enough because only one composition is typically
|
* Managing with array is enough because only one composition is typically
|
||||||
* there. Even if user switches native IME context, it's very rare that
|
* there. Even if user switches native IME context, it's very rare that
|
||||||
* second or more composition is started.
|
* second or more composition is started.
|
||||||
* It's assumed that this is used by nsIMEStateManager for storing all active
|
* It's assumed that this is used by IMEStateManager for storing all active
|
||||||
* compositions in the process. If the instance is it, each TextComposition
|
* compositions in the process. If the instance is it, each TextComposition
|
||||||
* in the array can be destroyed by calling some methods of itself.
|
* in the array can be destroyed by calling some methods of itself.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -27,6 +27,7 @@ EXPORTS += [
|
||||||
]
|
]
|
||||||
|
|
||||||
EXPORTS.mozilla += [
|
EXPORTS.mozilla += [
|
||||||
|
'IMEStateManager.h',
|
||||||
'InternalMutationEvent.h',
|
'InternalMutationEvent.h',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -77,6 +78,8 @@ UNIFIED_SOURCES += [
|
||||||
'Event.cpp',
|
'Event.cpp',
|
||||||
'EventTarget.cpp',
|
'EventTarget.cpp',
|
||||||
'FocusEvent.cpp',
|
'FocusEvent.cpp',
|
||||||
|
'IMEContentObserver.cpp',
|
||||||
|
'IMEStateManager.cpp',
|
||||||
'KeyboardEvent.cpp',
|
'KeyboardEvent.cpp',
|
||||||
'MessageEvent.cpp',
|
'MessageEvent.cpp',
|
||||||
'MouseEvent.cpp',
|
'MouseEvent.cpp',
|
||||||
|
@ -90,7 +93,6 @@ UNIFIED_SOURCES += [
|
||||||
'nsEventDispatcher.cpp',
|
'nsEventDispatcher.cpp',
|
||||||
'nsEventListenerManager.cpp',
|
'nsEventListenerManager.cpp',
|
||||||
'nsEventListenerService.cpp',
|
'nsEventListenerService.cpp',
|
||||||
'nsIMEStateManager.cpp',
|
|
||||||
'nsJSEventListener.cpp',
|
'nsJSEventListener.cpp',
|
||||||
'nsPaintRequest.cpp',
|
'nsPaintRequest.cpp',
|
||||||
'PointerEvent.cpp',
|
'PointerEvent.cpp',
|
||||||
|
|
|
@ -24,9 +24,9 @@
|
||||||
#include "nsISelectionPrivate.h"
|
#include "nsISelectionPrivate.h"
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
#include "nsLayoutUtils.h"
|
#include "nsLayoutUtils.h"
|
||||||
#include "nsIMEStateManager.h"
|
|
||||||
#include "nsIObjectFrame.h"
|
#include "nsIObjectFrame.h"
|
||||||
#include "mozilla/dom/Element.h"
|
#include "mozilla/dom/Element.h"
|
||||||
|
#include "mozilla/IMEStateManager.h"
|
||||||
#include "mozilla/TextEvents.h"
|
#include "mozilla/TextEvents.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
@ -1096,8 +1096,8 @@ nsContentEventHandler::OnSelectionEvent(WidgetSelectionEvent* aEvent)
|
||||||
// Get selection to manipulate
|
// Get selection to manipulate
|
||||||
// XXX why do we need to get them from ISM? This method should work fine
|
// XXX why do we need to get them from ISM? This method should work fine
|
||||||
// without ISM.
|
// without ISM.
|
||||||
nsresult rv = nsIMEStateManager::
|
nsresult rv =
|
||||||
GetFocusSelectionAndRoot(getter_AddRefs(mSelection),
|
IMEStateManager::GetFocusSelectionAndRoot(getter_AddRefs(mSelection),
|
||||||
getter_AddRefs(mRootContent));
|
getter_AddRefs(mRootContent));
|
||||||
if (rv != NS_ERROR_NOT_AVAILABLE) {
|
if (rv != NS_ERROR_NOT_AVAILABLE) {
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
|
@ -69,7 +69,7 @@ public:
|
||||||
// FlatText means the text that is generated from DOM tree. The BR elements
|
// FlatText means the text that is generated from DOM tree. The BR elements
|
||||||
// are replaced to native linefeeds. Other elements are ignored.
|
// are replaced to native linefeeds. Other elements are ignored.
|
||||||
|
|
||||||
// Get the offset in FlatText of the range. (also used by nsIMEStateManager)
|
// Get the offset in FlatText of the range. (also used by IMEContentObserver)
|
||||||
static nsresult GetFlatTextOffsetOfRange(nsIContent* aRootContent,
|
static nsresult GetFlatTextOffsetOfRange(nsIContent* aRootContent,
|
||||||
nsINode* aNode,
|
nsINode* aNode,
|
||||||
int32_t aNodeOffset,
|
int32_t aNodeOffset,
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
|
#include "mozilla/IMEStateManager.h"
|
||||||
#include "mozilla/MiscEvents.h"
|
#include "mozilla/MiscEvents.h"
|
||||||
#include "mozilla/MathAlgorithms.h"
|
#include "mozilla/MathAlgorithms.h"
|
||||||
#include "mozilla/MouseEvents.h"
|
#include "mozilla/MouseEvents.h"
|
||||||
|
@ -17,7 +18,6 @@
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsEventStateManager.h"
|
#include "nsEventStateManager.h"
|
||||||
#include "nsFocusManager.h"
|
#include "nsFocusManager.h"
|
||||||
#include "nsIMEStateManager.h"
|
|
||||||
#include "nsContentEventHandler.h"
|
#include "nsContentEventHandler.h"
|
||||||
#include "nsIContent.h"
|
#include "nsIContent.h"
|
||||||
#include "nsINodeInfo.h"
|
#include "nsINodeInfo.h"
|
||||||
|
@ -3765,7 +3765,7 @@ nsEventStateManager::IsTargetCrossProcess(WidgetGUIEvent* aEvent)
|
||||||
void
|
void
|
||||||
nsEventStateManager::NotifyDestroyPresContext(nsPresContext* aPresContext)
|
nsEventStateManager::NotifyDestroyPresContext(nsPresContext* aPresContext)
|
||||||
{
|
{
|
||||||
nsIMEStateManager::OnDestroyPresContext(aPresContext);
|
IMEStateManager::OnDestroyPresContext(aPresContext);
|
||||||
if (mHoverContent) {
|
if (mHoverContent) {
|
||||||
// Bug 70855: Presentation is going away, possibly for a reframe.
|
// Bug 70855: Presentation is going away, possibly for a reframe.
|
||||||
// Reset the hover state so that if we're recreating the presentation,
|
// Reset the hover state so that if we're recreating the presentation,
|
||||||
|
@ -5176,7 +5176,7 @@ nsEventStateManager::ContentRemoved(nsIDocument* aDocument, nsIContent* aContent
|
||||||
element->LeaveLink(element->GetPresContext());
|
element->LeaveLink(element->GetPresContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
nsIMEStateManager::OnRemoveContent(mPresContext, aContent);
|
IMEStateManager::OnRemoveContent(mPresContext, aContent);
|
||||||
|
|
||||||
// inform the focus manager that the content is being removed. If this
|
// inform the focus manager that the content is being removed. If this
|
||||||
// content is focused, the focus will be removed without firing events.
|
// content is focused, the focus will be removed without firing events.
|
||||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -917,6 +917,24 @@ interface WebGLExtensionTextureHalfFloatLinear
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
|
[NoInterfaceObject]
|
||||||
|
interface WebGLExtensionColorBufferFloat
|
||||||
|
{
|
||||||
|
const GLenum RGBA32F_EXT = 0x8814;
|
||||||
|
const GLenum RGB32F_EXT = 0x8815;
|
||||||
|
const GLenum FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT = 0x8211;
|
||||||
|
const GLenum UNSIGNED_NORMALIZED_EXT = 0x8C17;
|
||||||
|
};
|
||||||
|
|
||||||
|
[NoInterfaceObject]
|
||||||
|
interface WebGLExtensionColorBufferHalfFloat
|
||||||
|
{
|
||||||
|
const GLenum RGBA16F_EXT = 0x881A;
|
||||||
|
const GLenum RGB16F_EXT = 0x881B;
|
||||||
|
const GLenum FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT = 0x8211;
|
||||||
|
const GLenum UNSIGNED_NORMALIZED_EXT = 0x8C17;
|
||||||
|
};
|
||||||
|
|
||||||
[NoInterfaceObject]
|
[NoInterfaceObject]
|
||||||
interface WebGLExtensionVertexArray {
|
interface WebGLExtensionVertexArray {
|
||||||
const GLenum VERTEX_ARRAY_BINDING_OES = 0x85B5;
|
const GLenum VERTEX_ARRAY_BINDING_OES = 0x85B5;
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "mozFlushType.h" // for mozFlushType::Flush_Frames
|
#include "mozFlushType.h" // for mozFlushType::Flush_Frames
|
||||||
#include "mozISpellCheckingEngine.h"
|
#include "mozISpellCheckingEngine.h"
|
||||||
#include "mozInlineSpellChecker.h" // for mozInlineSpellChecker
|
#include "mozInlineSpellChecker.h" // for mozInlineSpellChecker
|
||||||
|
#include "mozilla/IMEStateManager.h" // for IMEStateManager
|
||||||
#include "mozilla/Preferences.h" // for Preferences
|
#include "mozilla/Preferences.h" // for Preferences
|
||||||
#include "mozilla/Selection.h" // for Selection, etc
|
#include "mozilla/Selection.h" // for Selection, etc
|
||||||
#include "mozilla/Services.h" // for GetObserverService
|
#include "mozilla/Services.h" // for GetObserverService
|
||||||
|
@ -75,7 +76,6 @@
|
||||||
#include "nsIFrame.h" // for nsIFrame
|
#include "nsIFrame.h" // for nsIFrame
|
||||||
#include "nsIHTMLDocument.h" // for nsIHTMLDocument
|
#include "nsIHTMLDocument.h" // for nsIHTMLDocument
|
||||||
#include "nsIInlineSpellChecker.h" // for nsIInlineSpellChecker, etc
|
#include "nsIInlineSpellChecker.h" // for nsIInlineSpellChecker, etc
|
||||||
#include "nsIMEStateManager.h" // for nsIMEStateManager
|
|
||||||
#include "nsNameSpaceManager.h" // for kNameSpaceID_None, etc
|
#include "nsNameSpaceManager.h" // for kNameSpaceID_None, etc
|
||||||
#include "nsINode.h" // for nsINode, etc
|
#include "nsINode.h" // for nsINode, etc
|
||||||
#include "nsIObserverService.h" // for nsIObserverService
|
#include "nsIObserverService.h" // for nsIObserverService
|
||||||
|
@ -315,7 +315,7 @@ nsEditor::PostCreate()
|
||||||
rv = GetPreferredIMEState(&newState);
|
rv = GetPreferredIMEState(&newState);
|
||||||
NS_ENSURE_SUCCESS(rv, NS_OK);
|
NS_ENSURE_SUCCESS(rv, NS_OK);
|
||||||
nsCOMPtr<nsIContent> content = GetFocusedContentForIME();
|
nsCOMPtr<nsIContent> content = GetFocusedContentForIME();
|
||||||
nsIMEStateManager::UpdateIMEState(newState, content);
|
IMEStateManager::UpdateIMEState(newState, content);
|
||||||
}
|
}
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -496,7 +496,7 @@ nsEditor::SetFlags(uint32_t aFlags)
|
||||||
// NOTE: When the enabled state isn't going to be modified, this method
|
// NOTE: When the enabled state isn't going to be modified, this method
|
||||||
// is going to do nothing.
|
// is going to do nothing.
|
||||||
nsCOMPtr<nsIContent> content = GetFocusedContentForIME();
|
nsCOMPtr<nsIContent> content = GetFocusedContentForIME();
|
||||||
nsIMEStateManager::UpdateIMEState(newState, content);
|
IMEStateManager::UpdateIMEState(newState, content);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2016,10 +2016,10 @@ nsEditor::EnsureComposition(mozilla::WidgetGUIEvent* aEvent)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// The compositionstart event must cause creating new TextComposition
|
// The compositionstart event must cause creating new TextComposition
|
||||||
// instance at being dispatched by nsIMEStateManager.
|
// instance at being dispatched by IMEStateManager.
|
||||||
mComposition = nsIMEStateManager::GetTextCompositionFor(aEvent);
|
mComposition = IMEStateManager::GetTextCompositionFor(aEvent);
|
||||||
if (!mComposition) {
|
if (!mComposition) {
|
||||||
MOZ_CRASH("nsIMEStateManager doesn't return proper composition");
|
MOZ_CRASH("IMEStateManager doesn't return proper composition");
|
||||||
}
|
}
|
||||||
mComposition->StartHandlingComposition(this);
|
mComposition->StartHandlingComposition(this);
|
||||||
}
|
}
|
||||||
|
@ -2095,10 +2095,10 @@ nsEditor::ForceCompositionEnd()
|
||||||
// Linux. Currently, nsGtkIMModule can know the timing of the cursor move,
|
// Linux. Currently, nsGtkIMModule can know the timing of the cursor move,
|
||||||
// so, the latter meaning should be gone.
|
// so, the latter meaning should be gone.
|
||||||
// XXX This may commit a composition in another editor.
|
// XXX This may commit a composition in another editor.
|
||||||
return nsIMEStateManager::NotifyIME(NOTIFY_IME_OF_CURSOR_POS_CHANGED, pc);
|
return IMEStateManager::NotifyIME(NOTIFY_IME_OF_CURSOR_POS_CHANGED, pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
return nsIMEStateManager::NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, pc);
|
return IMEStateManager::NotifyIME(REQUEST_TO_COMMIT_COMPOSITION, pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
|
|
@ -770,7 +770,7 @@ public:
|
||||||
// Get the focused content, if we're focused. Returns null otherwise.
|
// Get the focused content, if we're focused. Returns null otherwise.
|
||||||
virtual already_AddRefed<nsIContent> GetFocusedContent();
|
virtual already_AddRefed<nsIContent> GetFocusedContent();
|
||||||
|
|
||||||
// Get the focused content for the argument of some nsIMEStateManager's
|
// Get the focused content for the argument of some IMEStateManager's
|
||||||
// methods.
|
// methods.
|
||||||
virtual already_AddRefed<nsIContent> GetFocusedContentForIME();
|
virtual already_AddRefed<nsIContent> GetFocusedContentForIME();
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
|
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
|
||||||
|
#include "mozilla/IMEStateManager.h" // for IMEStateManager
|
||||||
#include "mozilla/Preferences.h" // for Preferences
|
#include "mozilla/Preferences.h" // for Preferences
|
||||||
#include "mozilla/TextEvents.h" // for WidgetCompositionEvent
|
#include "mozilla/TextEvents.h" // for WidgetCompositionEvent
|
||||||
#include "mozilla/dom/Element.h" // for Element
|
#include "mozilla/dom/Element.h" // for Element
|
||||||
|
@ -38,7 +39,6 @@
|
||||||
#include "nsIFocusManager.h" // for nsIFocusManager
|
#include "nsIFocusManager.h" // for nsIFocusManager
|
||||||
#include "nsIFormControl.h" // for nsIFormControl, etc
|
#include "nsIFormControl.h" // for nsIFormControl, etc
|
||||||
#include "nsIHTMLEditor.h" // for nsIHTMLEditor
|
#include "nsIHTMLEditor.h" // for nsIHTMLEditor
|
||||||
#include "nsIMEStateManager.h" // for nsIMEStateManager
|
|
||||||
#include "nsINativeKeyBindings.h" // for nsINativeKeyBindings
|
#include "nsINativeKeyBindings.h" // for nsINativeKeyBindings
|
||||||
#include "nsINode.h" // for nsINode, ::NODE_IS_EDITABLE, etc
|
#include "nsINode.h" // for nsINode, ::NODE_IS_EDITABLE, etc
|
||||||
#include "nsIPlaintextEditor.h" // for nsIPlaintextEditor, etc
|
#include "nsIPlaintextEditor.h" // for nsIPlaintextEditor, etc
|
||||||
|
@ -570,7 +570,7 @@ nsEditorEventListener::MouseClick(nsIDOMEvent* aMouseEvent)
|
||||||
nsPresContext* presContext =
|
nsPresContext* presContext =
|
||||||
presShell ? presShell->GetPresContext() : nullptr;
|
presShell ? presShell->GetPresContext() : nullptr;
|
||||||
if (presContext && currentDoc) {
|
if (presContext && currentDoc) {
|
||||||
nsIMEStateManager::OnClickInEditor(presContext,
|
IMEStateManager::OnClickInEditor(presContext,
|
||||||
currentDoc->HasFlag(NODE_IS_EDITABLE) ? nullptr : focusedContent,
|
currentDoc->HasFlag(NODE_IS_EDITABLE) ? nullptr : focusedContent,
|
||||||
mouseEvent);
|
mouseEvent);
|
||||||
}
|
}
|
||||||
|
@ -954,7 +954,7 @@ nsEditorEventListener::Focus(nsIDOMEvent* aEvent)
|
||||||
nsCOMPtr<nsIPresShell> ps = GetPresShell();
|
nsCOMPtr<nsIPresShell> ps = GetPresShell();
|
||||||
NS_ENSURE_TRUE(ps, NS_OK);
|
NS_ENSURE_TRUE(ps, NS_OK);
|
||||||
nsCOMPtr<nsIContent> focusedContent = mEditor->GetFocusedContentForIME();
|
nsCOMPtr<nsIContent> focusedContent = mEditor->GetFocusedContentForIME();
|
||||||
nsIMEStateManager::OnFocusInEditor(ps->GetPresContext(), focusedContent);
|
IMEStateManager::OnFocusInEditor(ps->GetPresContext(), focusedContent);
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,6 +86,9 @@ static const char *sExtensionNames[] = {
|
||||||
"GL_OES_texture_half_float",
|
"GL_OES_texture_half_float",
|
||||||
"GL_OES_texture_half_float_linear",
|
"GL_OES_texture_half_float_linear",
|
||||||
"GL_NV_half_float",
|
"GL_NV_half_float",
|
||||||
|
"GL_EXT_color_buffer_float",
|
||||||
|
"GL_EXT_color_buffer_half_float",
|
||||||
|
"GL_ARB_color_buffer_float",
|
||||||
"GL_EXT_unpack_subimage",
|
"GL_EXT_unpack_subimage",
|
||||||
"GL_OES_standard_derivatives",
|
"GL_OES_standard_derivatives",
|
||||||
"GL_EXT_texture_filter_anisotropic",
|
"GL_EXT_texture_filter_anisotropic",
|
||||||
|
|
|
@ -90,6 +90,7 @@ MOZ_BEGIN_ENUM_CLASS(GLFeature)
|
||||||
element_index_uint,
|
element_index_uint,
|
||||||
ES2_compatibility,
|
ES2_compatibility,
|
||||||
ES3_compatibility,
|
ES3_compatibility,
|
||||||
|
frag_color_float,
|
||||||
frag_depth,
|
frag_depth,
|
||||||
framebuffer_blit,
|
framebuffer_blit,
|
||||||
framebuffer_multisample,
|
framebuffer_multisample,
|
||||||
|
@ -102,6 +103,8 @@ MOZ_BEGIN_ENUM_CLASS(GLFeature)
|
||||||
occlusion_query2,
|
occlusion_query2,
|
||||||
packed_depth_stencil,
|
packed_depth_stencil,
|
||||||
query_objects,
|
query_objects,
|
||||||
|
renderbuffer_color_float,
|
||||||
|
renderbuffer_color_half_float,
|
||||||
robustness,
|
robustness,
|
||||||
sRGB,
|
sRGB,
|
||||||
standard_derivatives,
|
standard_derivatives,
|
||||||
|
@ -365,6 +368,9 @@ public:
|
||||||
OES_texture_half_float,
|
OES_texture_half_float,
|
||||||
OES_texture_half_float_linear,
|
OES_texture_half_float_linear,
|
||||||
NV_half_float,
|
NV_half_float,
|
||||||
|
EXT_color_buffer_float,
|
||||||
|
EXT_color_buffer_half_float,
|
||||||
|
ARB_color_buffer_float,
|
||||||
EXT_unpack_subimage,
|
EXT_unpack_subimage,
|
||||||
OES_standard_derivatives,
|
OES_standard_derivatives,
|
||||||
EXT_texture_filter_anisotropic,
|
EXT_texture_filter_anisotropic,
|
||||||
|
|
|
@ -111,6 +111,18 @@ static const FeatureInfo sFeatureInfoArr[] = {
|
||||||
GLContext::Extensions_End
|
GLContext::Extensions_End
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
// Removes clamping for float color outputs from frag shaders.
|
||||||
|
"frag_color_float",
|
||||||
|
300, // OpenGL version
|
||||||
|
300, // OpenGL ES version
|
||||||
|
{
|
||||||
|
GLContext::ARB_color_buffer_float,
|
||||||
|
GLContext::EXT_color_buffer_float,
|
||||||
|
GLContext::EXT_color_buffer_half_float,
|
||||||
|
GLContext::Extensions_End
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"frag_depth",
|
"frag_depth",
|
||||||
200, // OpenGL version
|
200, // OpenGL version
|
||||||
|
@ -252,6 +264,26 @@ static const FeatureInfo sFeatureInfoArr[] = {
|
||||||
* (added in OpenGL ES 3.0)
|
* (added in OpenGL ES 3.0)
|
||||||
*/
|
*/
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"renderbuffer_float",
|
||||||
|
300, // OpenGL version
|
||||||
|
300, // OpenGL ES version
|
||||||
|
{
|
||||||
|
GLContext::ARB_texture_float,
|
||||||
|
GLContext::EXT_color_buffer_float,
|
||||||
|
GLContext::Extensions_End
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"renderbuffer_half_float",
|
||||||
|
300, // OpenGL version
|
||||||
|
300, // OpenGL ES version
|
||||||
|
{
|
||||||
|
GLContext::ARB_texture_float,
|
||||||
|
GLContext::EXT_color_buffer_half_float,
|
||||||
|
GLContext::Extensions_End
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"robustness",
|
"robustness",
|
||||||
0, // OpenGL version
|
0, // OpenGL version
|
||||||
|
@ -282,7 +314,7 @@ static const FeatureInfo sFeatureInfoArr[] = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"texture_float",
|
"texture_float",
|
||||||
310, // OpenGL version
|
300, // OpenGL version
|
||||||
300, // OpenGL ES version
|
300, // OpenGL ES version
|
||||||
{
|
{
|
||||||
GLContext::ARB_texture_float,
|
GLContext::ARB_texture_float,
|
||||||
|
@ -302,7 +334,7 @@ static const FeatureInfo sFeatureInfoArr[] = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"texture_half_float",
|
"texture_half_float",
|
||||||
310, // OpenGL version
|
300, // OpenGL version
|
||||||
300, // OpenGL ES version
|
300, // OpenGL ES version
|
||||||
{
|
{
|
||||||
GLContext::ARB_half_float_pixel,
|
GLContext::ARB_half_float_pixel,
|
||||||
|
|
|
@ -14,7 +14,8 @@ NS_IMPL_ISUPPORTS1(GfxTexturesReporter, nsIMemoryReporter)
|
||||||
|
|
||||||
int64_t GfxTexturesReporter::sAmount = 0;
|
int64_t GfxTexturesReporter::sAmount = 0;
|
||||||
|
|
||||||
static uint32_t GetBitsPerTexel(GLenum format, GLenum type)
|
static uint32_t
|
||||||
|
GetBitsPerTexel(GLenum format, GLenum type)
|
||||||
{
|
{
|
||||||
// If there is no defined format or type, we're not taking up any memory
|
// If there is no defined format or type, we're not taking up any memory
|
||||||
if (!format || !type) {
|
if (!format || !type) {
|
||||||
|
@ -23,16 +24,16 @@ static uint32_t GetBitsPerTexel(GLenum format, GLenum type)
|
||||||
|
|
||||||
if (format == LOCAL_GL_DEPTH_COMPONENT) {
|
if (format == LOCAL_GL_DEPTH_COMPONENT) {
|
||||||
if (type == LOCAL_GL_UNSIGNED_SHORT)
|
if (type == LOCAL_GL_UNSIGNED_SHORT)
|
||||||
return 2;
|
return 2*8;
|
||||||
else if (type == LOCAL_GL_UNSIGNED_INT)
|
else if (type == LOCAL_GL_UNSIGNED_INT)
|
||||||
return 4;
|
return 4*8;
|
||||||
} else if (format == LOCAL_GL_DEPTH_STENCIL) {
|
} else if (format == LOCAL_GL_DEPTH_STENCIL) {
|
||||||
if (type == LOCAL_GL_UNSIGNED_INT_24_8_EXT)
|
if (type == LOCAL_GL_UNSIGNED_INT_24_8_EXT)
|
||||||
return 4;
|
return 4*8;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == LOCAL_GL_UNSIGNED_BYTE || type == LOCAL_GL_FLOAT) {
|
if (type == LOCAL_GL_UNSIGNED_BYTE || type == LOCAL_GL_FLOAT) {
|
||||||
int multiplier = type == LOCAL_GL_FLOAT ? 32 : 8;
|
uint32_t multiplier = type == LOCAL_GL_FLOAT ? 32 : 8;
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case LOCAL_GL_ALPHA:
|
case LOCAL_GL_ALPHA:
|
||||||
case LOCAL_GL_LUMINANCE:
|
case LOCAL_GL_LUMINANCE:
|
||||||
|
@ -64,7 +65,7 @@ static uint32_t GetBitsPerTexel(GLenum format, GLenum type)
|
||||||
type == LOCAL_GL_UNSIGNED_SHORT_5_5_5_1 ||
|
type == LOCAL_GL_UNSIGNED_SHORT_5_5_5_1 ||
|
||||||
type == LOCAL_GL_UNSIGNED_SHORT_5_6_5)
|
type == LOCAL_GL_UNSIGNED_SHORT_5_6_5)
|
||||||
{
|
{
|
||||||
return 16;
|
return 2*8;
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(false);
|
MOZ_ASSERT(false);
|
||||||
|
@ -75,8 +76,8 @@ static uint32_t GetBitsPerTexel(GLenum format, GLenum type)
|
||||||
GfxTexturesReporter::UpdateAmount(MemoryUse action, GLenum format,
|
GfxTexturesReporter::UpdateAmount(MemoryUse action, GLenum format,
|
||||||
GLenum type, uint16_t tileSize)
|
GLenum type, uint16_t tileSize)
|
||||||
{
|
{
|
||||||
uint32_t bytesPerTexel = GetBitsPerTexel(format, type) / 8;
|
int64_t bitsPerTexel = GetBitsPerTexel(format, type);
|
||||||
int64_t bytes = (int64_t)(tileSize * tileSize * bytesPerTexel);
|
int64_t bytes = int64_t(tileSize) * int64_t(tileSize) * bitsPerTexel/8;
|
||||||
if (action == MemoryFreed) {
|
if (action == MemoryFreed) {
|
||||||
sAmount -= bytes;
|
sAmount -= bytes;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -132,6 +132,23 @@ enum SurfaceInitMode
|
||||||
INIT_MODE_CLEAR
|
INIT_MODE_CLEAR
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A base class for a platform-dependent helper for use by TextureHost.
|
||||||
|
*/
|
||||||
|
class CompositorBackendSpecificData : public RefCounted<CompositorBackendSpecificData>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MOZ_DECLARE_REFCOUNTED_TYPENAME(CompositorBackendSpecificData)
|
||||||
|
CompositorBackendSpecificData()
|
||||||
|
{
|
||||||
|
MOZ_COUNT_CTOR(CompositorBackendSpecificData);
|
||||||
|
}
|
||||||
|
virtual ~CompositorBackendSpecificData()
|
||||||
|
{
|
||||||
|
MOZ_COUNT_DTOR(CompositorBackendSpecificData);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Common interface for compositor backends.
|
* Common interface for compositor backends.
|
||||||
*
|
*
|
||||||
|
@ -459,6 +476,10 @@ public:
|
||||||
return fillRatio;
|
return fillRatio;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual CompositorBackendSpecificData* GetCompositorBackendSpecificData() {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void DrawDiagnosticsInternal(DiagnosticFlags aFlags,
|
void DrawDiagnosticsInternal(DiagnosticFlags aFlags,
|
||||||
const gfx::Rect& aVisibleRect,
|
const gfx::Rect& aVisibleRect,
|
||||||
|
|
|
@ -384,6 +384,7 @@ struct RemoteImageData {
|
||||||
class ImageContainer : public SupportsWeakPtr<ImageContainer> {
|
class ImageContainer : public SupportsWeakPtr<ImageContainer> {
|
||||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ImageContainer)
|
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ImageContainer)
|
||||||
public:
|
public:
|
||||||
|
MOZ_DECLARE_REFCOUNTED_TYPENAME(ImageContainer)
|
||||||
|
|
||||||
enum { DISABLE_ASYNC = 0x0, ENABLE_ASYNC = 0x01 };
|
enum { DISABLE_ASYNC = 0x0, ENABLE_ASYNC = 0x01 };
|
||||||
|
|
||||||
|
|
|
@ -596,19 +596,12 @@ public:
|
||||||
|
|
||||||
bool IsInTransaction() const { return mInTransaction; }
|
bool IsInTransaction() const { return mInTransaction; }
|
||||||
|
|
||||||
virtual void AddRegionToClear(const nsIntRegion& aRegion)
|
|
||||||
{
|
|
||||||
mRegionToClear.Or(mRegionToClear, aRegion);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
nsRefPtr<Layer> mRoot;
|
nsRefPtr<Layer> mRoot;
|
||||||
gfx::UserData mUserData;
|
gfx::UserData mUserData;
|
||||||
bool mDestroyed;
|
bool mDestroyed;
|
||||||
bool mSnapEffectiveTransforms;
|
bool mSnapEffectiveTransforms;
|
||||||
|
|
||||||
nsIntRegion mRegionToClear;
|
|
||||||
|
|
||||||
// Print interesting information about this into aTo. Internally
|
// Print interesting information about this into aTo. Internally
|
||||||
// used to implement Dump*() and Log*().
|
// used to implement Dump*() and Log*().
|
||||||
virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix);
|
virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix);
|
||||||
|
@ -1342,7 +1335,6 @@ public:
|
||||||
|
|
||||||
virtual LayerRenderState GetRenderState() { return LayerRenderState(); }
|
virtual LayerRenderState GetRenderState() { return LayerRenderState(); }
|
||||||
|
|
||||||
|
|
||||||
void Mutated()
|
void Mutated()
|
||||||
{
|
{
|
||||||
mManager->Mutated(this);
|
mManager->Mutated(this);
|
||||||
|
|
|
@ -182,7 +182,7 @@ private:
|
||||||
bool IsPlaceholder(Tile aTile) const { return aTile == AsDerived().GetPlaceholderTile(); }
|
bool IsPlaceholder(Tile aTile) const { return aTile == AsDerived().GetPlaceholderTile(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class BasicTiledLayerBuffer;
|
class ClientTiledLayerBuffer;
|
||||||
class SurfaceDescriptorTiles;
|
class SurfaceDescriptorTiles;
|
||||||
class ISurfaceAllocator;
|
class ISurfaceAllocator;
|
||||||
|
|
||||||
|
@ -195,10 +195,10 @@ public:
|
||||||
* Update the current retained layer with the updated layer data.
|
* Update the current retained layer with the updated layer data.
|
||||||
* It is expected that the tiles described by aTiledDescriptor are all in the
|
* It is expected that the tiles described by aTiledDescriptor are all in the
|
||||||
* ReadLock state, so that the locks can be adopted when recreating a
|
* ReadLock state, so that the locks can be adopted when recreating a
|
||||||
* BasicTiledLayerBuffer locally. This lock will be retained until the buffer
|
* ClientTiledLayerBuffer locally. This lock will be retained until the buffer
|
||||||
* has completed uploading.
|
* has completed uploading.
|
||||||
*/
|
*/
|
||||||
virtual void PaintedTiledLayerBuffer(ISurfaceAllocator* aAllocator,
|
virtual void UseTiledLayerBuffer(ISurfaceAllocator* aAllocator,
|
||||||
const SurfaceDescriptorTiles& aTiledDescriptor) = 0;
|
const SurfaceDescriptorTiles& aTiledDescriptor) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -292,6 +292,7 @@ TiledLayerBuffer<Derived, Tile>::Update(const nsIntRegion& aNewValidRegion,
|
||||||
// TODO: Add a tile pool to reduce new allocation
|
// TODO: Add a tile pool to reduce new allocation
|
||||||
int tileX = 0;
|
int tileX = 0;
|
||||||
int tileY = 0;
|
int tileY = 0;
|
||||||
|
int tilesMissing = 0;
|
||||||
// Iterate over the new drawing bounds in steps of tiles.
|
// Iterate over the new drawing bounds in steps of tiles.
|
||||||
for (int32_t x = newBound.x; x < newBound.XMost(); tileX++) {
|
for (int32_t x = newBound.x; x < newBound.XMost(); tileX++) {
|
||||||
// Compute tileRect(x,y,width,height) in layer space coordinate
|
// Compute tileRect(x,y,width,height) in layer space coordinate
|
||||||
|
@ -336,6 +337,10 @@ TiledLayerBuffer<Derived, Tile>::Update(const nsIntRegion& aNewValidRegion,
|
||||||
// valid content because then we know we can safely recycle
|
// valid content because then we know we can safely recycle
|
||||||
// with taking from a tile that has recyclable content.
|
// with taking from a tile that has recyclable content.
|
||||||
newRetainedTiles.AppendElement(AsDerived().GetPlaceholderTile());
|
newRetainedTiles.AppendElement(AsDerived().GetPlaceholderTile());
|
||||||
|
|
||||||
|
if (aPaintRegion.Intersects(tileRect)) {
|
||||||
|
tilesMissing++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
y += height;
|
y += height;
|
||||||
|
@ -349,6 +354,26 @@ TiledLayerBuffer<Derived, Tile>::Update(const nsIntRegion& aNewValidRegion,
|
||||||
mRetainedWidth = tileX;
|
mRetainedWidth = tileX;
|
||||||
mRetainedHeight = tileY;
|
mRetainedHeight = tileY;
|
||||||
|
|
||||||
|
// Pass 1.5: Release excess tiles in oldRetainedTiles
|
||||||
|
// Tiles in oldRetainedTiles that aren't in newRetainedTiles will be recycled
|
||||||
|
// before creating new ones, but there could still be excess unnecessary
|
||||||
|
// tiles. As tiles may not have a fixed memory cost (for example, due to
|
||||||
|
// double-buffering), we should release these excess tiles first.
|
||||||
|
int oldTileCount = 0;
|
||||||
|
for (size_t i = 0; i < oldRetainedTiles.Length(); i++) {
|
||||||
|
Tile oldTile = oldRetainedTiles[i];
|
||||||
|
if (IsPlaceholder(oldTile)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oldTileCount >= tilesMissing) {
|
||||||
|
oldRetainedTiles[i] = AsDerived().GetPlaceholderTile();
|
||||||
|
AsDerived().ReleaseTile(oldTile);
|
||||||
|
} else {
|
||||||
|
oldTileCount ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NS_ABORT_IF_FALSE(aNewValidRegion.Contains(aPaintRegion), "Painting a region outside the visible region");
|
NS_ABORT_IF_FALSE(aNewValidRegion.Contains(aPaintRegion), "Painting a region outside the visible region");
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
nsIntRegion oldAndPainted(oldValidRegion);
|
nsIntRegion oldAndPainted(oldValidRegion);
|
||||||
|
@ -415,9 +440,15 @@ TiledLayerBuffer<Derived, Tile>::Update(const nsIntRegion& aNewValidRegion,
|
||||||
"index out of range");
|
"index out of range");
|
||||||
|
|
||||||
Tile newTile = newRetainedTiles[index];
|
Tile newTile = newRetainedTiles[index];
|
||||||
|
|
||||||
|
// Try to reuse a tile from the old retained tiles that had no partially
|
||||||
|
// valid content.
|
||||||
while (IsPlaceholder(newTile) && oldRetainedTiles.Length() > 0) {
|
while (IsPlaceholder(newTile) && oldRetainedTiles.Length() > 0) {
|
||||||
AsDerived().SwapTiles(newTile, oldRetainedTiles[oldRetainedTiles.Length()-1]);
|
AsDerived().SwapTiles(newTile, oldRetainedTiles[oldRetainedTiles.Length()-1]);
|
||||||
oldRetainedTiles.RemoveElementAt(oldRetainedTiles.Length()-1);
|
oldRetainedTiles.RemoveElementAt(oldRetainedTiles.Length()-1);
|
||||||
|
if (!IsPlaceholder(newTile)) {
|
||||||
|
oldTileCount--;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We've done our best effort to recycle a tile but it can be null
|
// We've done our best effort to recycle a tile but it can be null
|
||||||
|
@ -438,13 +469,8 @@ TiledLayerBuffer<Derived, Tile>::Update(const nsIntRegion& aNewValidRegion,
|
||||||
x += width;
|
x += width;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Throw away any tiles we didn't recycle
|
// At this point, oldTileCount should be zero
|
||||||
// TODO: Add a tile pool
|
NS_ABORT_IF_FALSE(oldTileCount == 0, "Failed to release old tiles");
|
||||||
while (oldRetainedTiles.Length() > 0) {
|
|
||||||
Tile oldTile = oldRetainedTiles[oldRetainedTiles.Length()-1];
|
|
||||||
oldRetainedTiles.RemoveElementAt(oldRetainedTiles.Length()-1);
|
|
||||||
AsDerived().ReleaseTile(oldTile);
|
|
||||||
}
|
|
||||||
|
|
||||||
mRetainedTiles = newRetainedTiles;
|
mRetainedTiles = newRetainedTiles;
|
||||||
mValidRegion = aNewValidRegion;
|
mValidRegion = aNewValidRegion;
|
||||||
|
|
|
@ -625,16 +625,6 @@ BasicLayerManager::EndTransactionInternal(DrawThebesLayerCallback aCallback,
|
||||||
}
|
}
|
||||||
|
|
||||||
PaintLayer(mTarget, mRoot, aCallback, aCallbackData, nullptr);
|
PaintLayer(mTarget, mRoot, aCallback, aCallbackData, nullptr);
|
||||||
if (!mRegionToClear.IsEmpty()) {
|
|
||||||
AutoSetOperator op(mTarget, gfxContext::OPERATOR_CLEAR);
|
|
||||||
nsIntRegionRectIterator iter(mRegionToClear);
|
|
||||||
const nsIntRect *r;
|
|
||||||
while ((r = iter.Next())) {
|
|
||||||
mTarget->NewPath();
|
|
||||||
mTarget->Rectangle(gfxRect(r->x, r->y, r->width, r->height));
|
|
||||||
mTarget->Fill();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (mWidget) {
|
if (mWidget) {
|
||||||
FlashWidgetUpdateArea(mTarget);
|
FlashWidgetUpdateArea(mTarget);
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,8 @@ class TextureClientX11
|
||||||
return mFormat;
|
return mFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return false; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
gfx::SurfaceFormat mFormat;
|
gfx::SurfaceFormat mFormat;
|
||||||
gfx::IntSize mSize;
|
gfx::IntSize mSize;
|
||||||
|
|
|
@ -99,13 +99,6 @@ CanvasClient2D::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TemporaryRef<BufferTextureClient>
|
|
||||||
CanvasClient2D::CreateBufferTextureClient(gfx::SurfaceFormat aFormat, TextureFlags aFlags)
|
|
||||||
{
|
|
||||||
return CompositableClient::CreateBufferTextureClient(aFormat,
|
|
||||||
mTextureInfo.mTextureFlags | aFlags);
|
|
||||||
}
|
|
||||||
|
|
||||||
CanvasClientSurfaceStream::CanvasClientSurfaceStream(CompositableForwarder* aLayerForwarder,
|
CanvasClientSurfaceStream::CanvasClientSurfaceStream(CompositableForwarder* aLayerForwarder,
|
||||||
TextureFlags aFlags)
|
TextureFlags aFlags)
|
||||||
: CanvasClient(aLayerForwarder, aFlags)
|
: CanvasClient(aLayerForwarder, aFlags)
|
||||||
|
|
|
@ -50,7 +50,7 @@ public:
|
||||||
TextureFlags aFlags);
|
TextureFlags aFlags);
|
||||||
|
|
||||||
CanvasClient(CompositableForwarder* aFwd, TextureFlags aFlags)
|
CanvasClient(CompositableForwarder* aFwd, TextureFlags aFlags)
|
||||||
: CompositableClient(aFwd)
|
: CompositableClient(aFwd, aFlags)
|
||||||
{
|
{
|
||||||
mTextureInfo.mTextureFlags = aFlags;
|
mTextureInfo.mTextureFlags = aFlags;
|
||||||
}
|
}
|
||||||
|
@ -95,10 +95,6 @@ public:
|
||||||
return CompositableClient::AddTextureClient(aTexture);
|
return CompositableClient::AddTextureClient(aTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual TemporaryRef<BufferTextureClient>
|
|
||||||
CreateBufferTextureClient(gfx::SurfaceFormat aFormat,
|
|
||||||
TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT) MOZ_OVERRIDE;
|
|
||||||
|
|
||||||
virtual void OnDetach() MOZ_OVERRIDE
|
virtual void OnDetach() MOZ_OVERRIDE
|
||||||
{
|
{
|
||||||
mBuffer = nullptr;
|
mBuffer = nullptr;
|
||||||
|
|
|
@ -20,10 +20,12 @@
|
||||||
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor
|
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor
|
||||||
#include "mozilla/layers/PLayerChild.h" // for PLayerChild
|
#include "mozilla/layers/PLayerChild.h" // for PLayerChild
|
||||||
#include "mozilla/layers/LayerTransactionChild.h"
|
#include "mozilla/layers/LayerTransactionChild.h"
|
||||||
|
#include "mozilla/layers/TextureClientPool.h" // for TextureClientPool
|
||||||
#include "nsAString.h"
|
#include "nsAString.h"
|
||||||
#include "nsIWidget.h" // for nsIWidget
|
#include "nsIWidget.h" // for nsIWidget
|
||||||
#include "nsTArray.h" // for AutoInfallibleTArray
|
#include "nsTArray.h" // for AutoInfallibleTArray
|
||||||
#include "nsXULAppAPI.h" // for XRE_GetProcessType, etc
|
#include "nsXULAppAPI.h" // for XRE_GetProcessType, etc
|
||||||
|
#include "TiledLayerBuffer.h"
|
||||||
#ifdef MOZ_WIDGET_ANDROID
|
#ifdef MOZ_WIDGET_ANDROID
|
||||||
#include "AndroidBridge.h"
|
#include "AndroidBridge.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -34,6 +36,11 @@ using namespace mozilla::gfx;
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace layers {
|
namespace layers {
|
||||||
|
|
||||||
|
TextureClientPoolMember::TextureClientPoolMember(SurfaceFormat aFormat, TextureClientPool* aTexturePool)
|
||||||
|
: mFormat(aFormat)
|
||||||
|
, mTexturePool(aTexturePool)
|
||||||
|
{}
|
||||||
|
|
||||||
ClientLayerManager::ClientLayerManager(nsIWidget* aWidget)
|
ClientLayerManager::ClientLayerManager(nsIWidget* aWidget)
|
||||||
: mPhase(PHASE_NONE)
|
: mPhase(PHASE_NONE)
|
||||||
, mWidget(aWidget)
|
, mWidget(aWidget)
|
||||||
|
@ -53,6 +60,8 @@ ClientLayerManager::~ClientLayerManager()
|
||||||
mRoot = nullptr;
|
mRoot = nullptr;
|
||||||
|
|
||||||
MOZ_COUNT_DTOR(ClientLayerManager);
|
MOZ_COUNT_DTOR(ClientLayerManager);
|
||||||
|
|
||||||
|
mTexturePools.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t
|
int32_t
|
||||||
|
@ -222,6 +231,11 @@ ClientLayerManager::EndTransaction(DrawThebesLayerCallback aCallback,
|
||||||
} else {
|
} else {
|
||||||
MakeSnapshotIfRequired();
|
MakeSnapshotIfRequired();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const TextureClientPoolMember* item = mTexturePools.getFirst();
|
||||||
|
item; item = item->getNext()) {
|
||||||
|
item->mTexturePool->ReturnDeferredClients();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -440,6 +454,26 @@ ClientLayerManager::SetIsFirstPaint()
|
||||||
mForwarder->SetIsFirstPaint();
|
mForwarder->SetIsFirstPaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TextureClientPool*
|
||||||
|
ClientLayerManager::GetTexturePool(SurfaceFormat aFormat)
|
||||||
|
{
|
||||||
|
for (const TextureClientPoolMember* item = mTexturePools.getFirst();
|
||||||
|
item; item = item->getNext()) {
|
||||||
|
if (item->mFormat == aFormat) {
|
||||||
|
return item->mTexturePool;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureClientPoolMember* texturePoolMember =
|
||||||
|
new TextureClientPoolMember(aFormat,
|
||||||
|
new TextureClientPool(aFormat, IntSize(TILEDLAYERBUFFER_TILE_SIZE,
|
||||||
|
TILEDLAYERBUFFER_TILE_SIZE),
|
||||||
|
mForwarder));
|
||||||
|
mTexturePools.insertBack(texturePoolMember);
|
||||||
|
|
||||||
|
return texturePoolMember->mTexturePool;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ClientLayerManager::ClearCachedResources(Layer* aSubtree)
|
ClientLayerManager::ClearCachedResources(Layer* aSubtree)
|
||||||
{
|
{
|
||||||
|
@ -452,6 +486,10 @@ ClientLayerManager::ClearCachedResources(Layer* aSubtree)
|
||||||
} else if (mRoot) {
|
} else if (mRoot) {
|
||||||
ClearLayer(mRoot);
|
ClearLayer(mRoot);
|
||||||
}
|
}
|
||||||
|
for (const TextureClientPoolMember* item = mTexturePools.getFirst();
|
||||||
|
item; item = item->getNext()) {
|
||||||
|
item->mTexturePool->Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "Layers.h"
|
#include "Layers.h"
|
||||||
#include "gfxContext.h" // for gfxContext
|
#include "gfxContext.h" // for gfxContext
|
||||||
#include "mozilla/Attributes.h" // for MOZ_OVERRIDE
|
#include "mozilla/Attributes.h" // for MOZ_OVERRIDE
|
||||||
|
#include "mozilla/LinkedList.h" // For LinkedList
|
||||||
#include "mozilla/WidgetUtils.h" // for ScreenRotation
|
#include "mozilla/WidgetUtils.h" // for ScreenRotation
|
||||||
#include "mozilla/gfx/Rect.h" // for Rect
|
#include "mozilla/gfx/Rect.h" // for Rect
|
||||||
#include "mozilla/layers/CompositorTypes.h"
|
#include "mozilla/layers/CompositorTypes.h"
|
||||||
|
@ -32,6 +33,16 @@ class ClientThebesLayer;
|
||||||
class CompositorChild;
|
class CompositorChild;
|
||||||
class ImageLayer;
|
class ImageLayer;
|
||||||
class PLayerChild;
|
class PLayerChild;
|
||||||
|
class TextureClientPool;
|
||||||
|
|
||||||
|
class TextureClientPoolMember
|
||||||
|
: public LinkedListElement<TextureClientPoolMember> {
|
||||||
|
public:
|
||||||
|
TextureClientPoolMember(gfx::SurfaceFormat aFormat, TextureClientPool* aTexturePool);
|
||||||
|
|
||||||
|
gfx::SurfaceFormat mFormat;
|
||||||
|
RefPtr<TextureClientPool> mTexturePool;
|
||||||
|
};
|
||||||
|
|
||||||
class ClientLayerManager : public LayerManager
|
class ClientLayerManager : public LayerManager
|
||||||
{
|
{
|
||||||
|
@ -96,6 +107,8 @@ public:
|
||||||
|
|
||||||
virtual void SetIsFirstPaint() MOZ_OVERRIDE;
|
virtual void SetIsFirstPaint() MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
TextureClientPool *GetTexturePool(gfx::SurfaceFormat aFormat);
|
||||||
|
|
||||||
// Drop cached resources and ask our shadow manager to do the same,
|
// Drop cached resources and ask our shadow manager to do the same,
|
||||||
// if we have one.
|
// if we have one.
|
||||||
virtual void ClearCachedResources(Layer* aSubtree = nullptr) MOZ_OVERRIDE;
|
virtual void ClearCachedResources(Layer* aSubtree = nullptr) MOZ_OVERRIDE;
|
||||||
|
@ -214,6 +227,7 @@ private:
|
||||||
bool mNeedsComposite;
|
bool mNeedsComposite;
|
||||||
|
|
||||||
RefPtr<ShadowLayerForwarder> mForwarder;
|
RefPtr<ShadowLayerForwarder> mForwarder;
|
||||||
|
LinkedList<TextureClientPoolMember> mTexturePools;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ClientLayer : public ShadowableLayer
|
class ClientLayer : public ShadowableLayer
|
||||||
|
|
|
@ -172,7 +172,10 @@ ClientLayerManager::CreateThebesLayerWithHint(ThebesLayerCreationHint aHint)
|
||||||
#ifdef MOZ_B2G
|
#ifdef MOZ_B2G
|
||||||
aHint == SCROLLABLE &&
|
aHint == SCROLLABLE &&
|
||||||
#endif
|
#endif
|
||||||
gfxPrefs::LayersTilesEnabled() && AsShadowForwarder()->GetCompositorBackendType() == LayersBackend::LAYERS_OPENGL) {
|
gfxPrefs::LayersTilesEnabled() &&
|
||||||
|
(AsShadowForwarder()->GetCompositorBackendType() == LayersBackend::LAYERS_OPENGL ||
|
||||||
|
AsShadowForwarder()->GetCompositorBackendType() == LayersBackend::LAYERS_D3D9 ||
|
||||||
|
AsShadowForwarder()->GetCompositorBackendType() == LayersBackend::LAYERS_D3D11)) {
|
||||||
nsRefPtr<ClientTiledThebesLayer> layer =
|
nsRefPtr<ClientTiledThebesLayer> layer =
|
||||||
new ClientTiledThebesLayer(this);
|
new ClientTiledThebesLayer(this);
|
||||||
CREATE_SHADOW(Thebes);
|
CREATE_SHADOW(Thebes);
|
||||||
|
|
|
@ -37,6 +37,14 @@ ClientTiledThebesLayer::~ClientTiledThebesLayer()
|
||||||
MOZ_COUNT_DTOR(ClientTiledThebesLayer);
|
MOZ_COUNT_DTOR(ClientTiledThebesLayer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ClientTiledThebesLayer::ClearCachedResources()
|
||||||
|
{
|
||||||
|
if (mContentClient) {
|
||||||
|
mContentClient->ClearCachedResources();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ClientTiledThebesLayer::FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
|
ClientTiledThebesLayer::FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
|
||||||
{
|
{
|
||||||
|
@ -189,7 +197,7 @@ ClientTiledThebesLayer::RenderLayer()
|
||||||
callback, data);
|
callback, data);
|
||||||
|
|
||||||
ClientManager()->Hold(this);
|
ClientManager()->Hold(this);
|
||||||
mContentClient->LockCopyAndWrite(TiledContentClient::TILED_BUFFER);
|
mContentClient->UseTiledLayerBuffer(TiledContentClient::TILED_BUFFER);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -262,7 +270,7 @@ ClientTiledThebesLayer::RenderLayer()
|
||||||
|
|
||||||
if (updatedBuffer) {
|
if (updatedBuffer) {
|
||||||
ClientManager()->Hold(this);
|
ClientManager()->Hold(this);
|
||||||
mContentClient->LockCopyAndWrite(TiledContentClient::TILED_BUFFER);
|
mContentClient->UseTiledLayerBuffer(TiledContentClient::TILED_BUFFER);
|
||||||
|
|
||||||
// If there are low precision updates, mark the paint as unfinished and
|
// If there are low precision updates, mark the paint as unfinished and
|
||||||
// request a repeat transaction.
|
// request a repeat transaction.
|
||||||
|
@ -331,7 +339,7 @@ ClientTiledThebesLayer::RenderLayer()
|
||||||
// and the associated resources can be freed.
|
// and the associated resources can be freed.
|
||||||
if (updatedLowPrecision) {
|
if (updatedLowPrecision) {
|
||||||
ClientManager()->Hold(this);
|
ClientManager()->Hold(this);
|
||||||
mContentClient->LockCopyAndWrite(TiledContentClient::LOW_PRECISION_TILED_BUFFER);
|
mContentClient->UseTiledLayerBuffer(TiledContentClient::LOW_PRECISION_TILED_BUFFER);
|
||||||
}
|
}
|
||||||
|
|
||||||
EndPaint(false);
|
EndPaint(false);
|
||||||
|
|
|
@ -63,6 +63,8 @@ public:
|
||||||
|
|
||||||
virtual void RenderLayer();
|
virtual void RenderLayer();
|
||||||
|
|
||||||
|
virtual void ClearCachedResources() MOZ_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ClientLayerManager* ClientManager()
|
ClientLayerManager* ClientManager()
|
||||||
{
|
{
|
||||||
|
|
|
@ -12,20 +12,9 @@
|
||||||
#include "mozilla/mozalloc.h" // for operator delete, etc
|
#include "mozilla/mozalloc.h" // for operator delete, etc
|
||||||
#include "gfxASurface.h" // for gfxContentType
|
#include "gfxASurface.h" // for gfxContentType
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
#include "mozilla/layers/TextureD3D9.h"
|
#include "gfxWindowsPlatform.h" // for gfxWindowsPlatform
|
||||||
#include "mozilla/layers/TextureD3D11.h"
|
#include "mozilla/layers/TextureD3D11.h"
|
||||||
#include "gfxWindowsPlatform.h"
|
#include "mozilla/layers/TextureD3D9.h"
|
||||||
#include "gfx2DGlue.h"
|
|
||||||
#endif
|
|
||||||
#ifdef MOZ_X11
|
|
||||||
#include "mozilla/layers/TextureClientX11.h"
|
|
||||||
#ifdef GL_PROVIDER_GLX
|
|
||||||
#include "GLXLibrary.h"
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#ifdef MOZ_WIDGET_GONK
|
|
||||||
#include <cutils/properties.h>
|
|
||||||
#include "mozilla/layers/GrallocTextureClient.h"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace mozilla::gfx;
|
using namespace mozilla::gfx;
|
||||||
|
@ -33,14 +22,15 @@ using namespace mozilla::gfx;
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace layers {
|
namespace layers {
|
||||||
|
|
||||||
CompositableClient::CompositableClient(CompositableForwarder* aForwarder)
|
CompositableClient::CompositableClient(CompositableForwarder* aForwarder,
|
||||||
|
TextureFlags aTextureFlags)
|
||||||
: mCompositableChild(nullptr)
|
: mCompositableChild(nullptr)
|
||||||
, mForwarder(aForwarder)
|
, mForwarder(aForwarder)
|
||||||
|
, mTextureFlags(aTextureFlags)
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(CompositableClient);
|
MOZ_COUNT_CTOR(CompositableClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CompositableClient::~CompositableClient()
|
CompositableClient::~CompositableClient()
|
||||||
{
|
{
|
||||||
MOZ_COUNT_DTOR(CompositableClient);
|
MOZ_COUNT_DTOR(CompositableClient);
|
||||||
|
@ -131,7 +121,7 @@ CompositableClient::CreateDeprecatedTextureClient(DeprecatedTextureClientType aD
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (parentBackend == LayersBackend::LAYERS_D3D9 &&
|
if (parentBackend == LayersBackend::LAYERS_D3D9 &&
|
||||||
!GetForwarder()->ForwardsToDifferentProcess()) {
|
GetForwarder()->IsSameProcess()) {
|
||||||
// We can't use a d3d9 texture for an RGBA surface because we cannot get a DC for
|
// We can't use a d3d9 texture for an RGBA surface because we cannot get a DC for
|
||||||
// for a gfxWindowsSurface.
|
// for a gfxWindowsSurface.
|
||||||
// We have to wait for the compositor thread to create a d3d9 device before we
|
// We have to wait for the compositor thread to create a d3d9 device before we
|
||||||
|
@ -181,117 +171,16 @@ TemporaryRef<BufferTextureClient>
|
||||||
CompositableClient::CreateBufferTextureClient(SurfaceFormat aFormat,
|
CompositableClient::CreateBufferTextureClient(SurfaceFormat aFormat,
|
||||||
TextureFlags aTextureFlags)
|
TextureFlags aTextureFlags)
|
||||||
{
|
{
|
||||||
// XXX - Once bug 908196 is fixed, we can use gralloc textures here which will
|
return TextureClient::CreateBufferTextureClient(GetForwarder(), aFormat,
|
||||||
// improve performances of videos using SharedPlanarYCbCrImage on b2g.
|
aTextureFlags | mTextureFlags);
|
||||||
//#ifdef MOZ_WIDGET_GONK
|
|
||||||
// {
|
|
||||||
// RefPtr<BufferTextureClient> result = new GrallocTextureClientOGL(this,
|
|
||||||
// aFormat,
|
|
||||||
// aTextureFlags);
|
|
||||||
// return result.forget();
|
|
||||||
// }
|
|
||||||
//#endif
|
|
||||||
if (gfxPlatform::GetPlatform()->PreferMemoryOverShmem()) {
|
|
||||||
RefPtr<BufferTextureClient> result = new MemoryTextureClient(this, aFormat, aTextureFlags);
|
|
||||||
return result.forget();
|
|
||||||
}
|
}
|
||||||
RefPtr<BufferTextureClient> result = new ShmemTextureClient(this, aFormat, aTextureFlags);
|
|
||||||
return result.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef MOZ_WIDGET_GONK
|
|
||||||
static bool
|
|
||||||
DisableGralloc(SurfaceFormat aFormat)
|
|
||||||
{
|
|
||||||
if (aFormat == gfx::SurfaceFormat::A8) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
#if ANDROID_VERSION <= 15
|
|
||||||
static bool checkedDevice = false;
|
|
||||||
static bool disableGralloc = false;
|
|
||||||
|
|
||||||
if (!checkedDevice) {
|
|
||||||
char propValue[PROPERTY_VALUE_MAX];
|
|
||||||
property_get("ro.product.device", propValue, "None");
|
|
||||||
|
|
||||||
if (strcmp("crespo",propValue) == 0) {
|
|
||||||
NS_WARNING("Nexus S has issues with gralloc, falling back to shmem");
|
|
||||||
disableGralloc = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
checkedDevice = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (disableGralloc) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
#else
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
TemporaryRef<TextureClient>
|
TemporaryRef<TextureClient>
|
||||||
CompositableClient::CreateTextureClientForDrawing(SurfaceFormat aFormat,
|
CompositableClient::CreateTextureClientForDrawing(SurfaceFormat aFormat,
|
||||||
TextureFlags aTextureFlags)
|
TextureFlags aTextureFlags)
|
||||||
{
|
{
|
||||||
RefPtr<TextureClient> result;
|
return TextureClient::CreateTextureClientForDrawing(GetForwarder(), aFormat,
|
||||||
|
aTextureFlags | mTextureFlags);
|
||||||
#ifdef XP_WIN
|
|
||||||
LayersBackend parentBackend = GetForwarder()->GetCompositorBackendType();
|
|
||||||
if (parentBackend == LayersBackend::LAYERS_D3D11 && gfxWindowsPlatform::GetPlatform()->GetD2DDevice() &&
|
|
||||||
!(aTextureFlags & TEXTURE_ALLOC_FALLBACK)) {
|
|
||||||
result = new TextureClientD3D11(aFormat, aTextureFlags);
|
|
||||||
}
|
|
||||||
if (parentBackend == LayersBackend::LAYERS_D3D9 &&
|
|
||||||
!GetForwarder()->ForwardsToDifferentProcess() &&
|
|
||||||
!(aTextureFlags & TEXTURE_ALLOC_FALLBACK)) {
|
|
||||||
if (!gfxWindowsPlatform::GetPlatform()->GetD3D9Device()) {
|
|
||||||
result = new DIBTextureClientD3D9(aFormat, aTextureFlags);
|
|
||||||
} else {
|
|
||||||
result = new CairoTextureClientD3D9(aFormat, aTextureFlags);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MOZ_X11
|
|
||||||
LayersBackend parentBackend = GetForwarder()->GetCompositorBackendType();
|
|
||||||
gfxSurfaceType type =
|
|
||||||
gfxPlatform::GetPlatform()->ScreenReferenceSurface()->GetType();
|
|
||||||
|
|
||||||
if (parentBackend == LayersBackend::LAYERS_BASIC &&
|
|
||||||
type == gfxSurfaceType::Xlib &&
|
|
||||||
!(aTextureFlags & TEXTURE_ALLOC_FALLBACK))
|
|
||||||
{
|
|
||||||
result = new TextureClientX11(aFormat, aTextureFlags);
|
|
||||||
}
|
|
||||||
#ifdef GL_PROVIDER_GLX
|
|
||||||
if (parentBackend == LayersBackend::LAYERS_OPENGL &&
|
|
||||||
type == gfxSurfaceType::Xlib &&
|
|
||||||
!(aTextureFlags & TEXTURE_ALLOC_FALLBACK) &&
|
|
||||||
aFormat != SurfaceFormat::A8 &&
|
|
||||||
gl::sGLXLibrary.UseTextureFromPixmap())
|
|
||||||
{
|
|
||||||
result = new TextureClientX11(aFormat, aTextureFlags);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef MOZ_WIDGET_GONK
|
|
||||||
if (!DisableGralloc(aFormat)) {
|
|
||||||
result = new GrallocTextureClientOGL(this, aFormat, aTextureFlags);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Can't do any better than a buffer texture client.
|
|
||||||
if (!result) {
|
|
||||||
result = CreateBufferTextureClient(aFormat, aTextureFlags);
|
|
||||||
}
|
|
||||||
|
|
||||||
MOZ_ASSERT(!result || result->AsTextureClientDrawTarget(),
|
|
||||||
"Not a TextureClientDrawTarget?");
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -73,7 +73,7 @@ class CompositableClient : public AtomicRefCounted<CompositableClient>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MOZ_DECLARE_REFCOUNTED_TYPENAME(CompositableClient)
|
MOZ_DECLARE_REFCOUNTED_TYPENAME(CompositableClient)
|
||||||
CompositableClient(CompositableForwarder* aForwarder);
|
CompositableClient(CompositableForwarder* aForwarder, TextureFlags aFlags = 0);
|
||||||
|
|
||||||
virtual ~CompositableClient();
|
virtual ~CompositableClient();
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ public:
|
||||||
CreateDeprecatedTextureClient(DeprecatedTextureClientType aDeprecatedTextureClientType,
|
CreateDeprecatedTextureClient(DeprecatedTextureClientType aDeprecatedTextureClientType,
|
||||||
gfxContentType aContentType = gfxContentType::SENTINEL);
|
gfxContentType aContentType = gfxContentType::SENTINEL);
|
||||||
|
|
||||||
virtual TemporaryRef<BufferTextureClient>
|
TemporaryRef<BufferTextureClient>
|
||||||
CreateBufferTextureClient(gfx::SurfaceFormat aFormat,
|
CreateBufferTextureClient(gfx::SurfaceFormat aFormat,
|
||||||
TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT);
|
TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT);
|
||||||
|
|
||||||
|
@ -143,9 +143,18 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual void OnDetach() {}
|
virtual void OnDetach() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear any resources that are not immediately necessary. This may be called
|
||||||
|
* in low-memory conditions.
|
||||||
|
*/
|
||||||
|
virtual void ClearCachedResources() {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CompositableChild* mCompositableChild;
|
CompositableChild* mCompositableChild;
|
||||||
CompositableForwarder* mForwarder;
|
CompositableForwarder* mForwarder;
|
||||||
|
// Some layers may want to enforce some flags to all their textures
|
||||||
|
// (like disallowing tiling)
|
||||||
|
TextureFlags mTextureFlags;
|
||||||
|
|
||||||
friend class CompositableChild;
|
friend class CompositableChild;
|
||||||
};
|
};
|
||||||
|
|
|
@ -82,8 +82,7 @@ ImageClient::CreateImageClient(CompositableType aCompositableHostType,
|
||||||
ImageClientSingle::ImageClientSingle(CompositableForwarder* aFwd,
|
ImageClientSingle::ImageClientSingle(CompositableForwarder* aFwd,
|
||||||
TextureFlags aFlags,
|
TextureFlags aFlags,
|
||||||
CompositableType aType)
|
CompositableType aType)
|
||||||
: ImageClient(aFwd, aType)
|
: ImageClient(aFwd, aFlags, aType)
|
||||||
, mTextureFlags(aFlags)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -310,12 +309,6 @@ ImageClientSingle::AddTextureClient(TextureClient* aTexture)
|
||||||
return CompositableClient::AddTextureClient(aTexture);
|
return CompositableClient::AddTextureClient(aTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
TemporaryRef<BufferTextureClient>
|
|
||||||
ImageClientSingle::CreateBufferTextureClient(gfx::SurfaceFormat aFormat, TextureFlags aFlags)
|
|
||||||
{
|
|
||||||
return CompositableClient::CreateBufferTextureClient(aFormat, mTextureFlags | aFlags);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ImageClientSingle::OnDetach()
|
ImageClientSingle::OnDetach()
|
||||||
{
|
{
|
||||||
|
@ -329,8 +322,9 @@ ImageClientBuffered::OnDetach()
|
||||||
mBackBuffer = nullptr;
|
mBackBuffer = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageClient::ImageClient(CompositableForwarder* aFwd, CompositableType aType)
|
ImageClient::ImageClient(CompositableForwarder* aFwd, TextureFlags aFlags,
|
||||||
: CompositableClient(aFwd)
|
CompositableType aType)
|
||||||
|
: CompositableClient(aFwd, aFlags)
|
||||||
, mType(aType)
|
, mType(aType)
|
||||||
, mLastPaintedImageSerial(0)
|
, mLastPaintedImageSerial(0)
|
||||||
{}
|
{}
|
||||||
|
@ -349,7 +343,7 @@ ImageClient::UpdatePictureRect(nsIntRect aRect)
|
||||||
DeprecatedImageClientSingle::DeprecatedImageClientSingle(CompositableForwarder* aFwd,
|
DeprecatedImageClientSingle::DeprecatedImageClientSingle(CompositableForwarder* aFwd,
|
||||||
TextureFlags aFlags,
|
TextureFlags aFlags,
|
||||||
CompositableType aType)
|
CompositableType aType)
|
||||||
: ImageClient(aFwd, aType)
|
: ImageClient(aFwd, aFlags, aType)
|
||||||
, mTextureInfo(aType)
|
, mTextureInfo(aType)
|
||||||
{
|
{
|
||||||
mTextureInfo.mTextureFlags = aFlags;
|
mTextureInfo.mTextureFlags = aFlags;
|
||||||
|
@ -482,7 +476,7 @@ DeprecatedImageClientSingle::Updated()
|
||||||
|
|
||||||
ImageClientBridge::ImageClientBridge(CompositableForwarder* aFwd,
|
ImageClientBridge::ImageClientBridge(CompositableForwarder* aFwd,
|
||||||
TextureFlags aFlags)
|
TextureFlags aFlags)
|
||||||
: ImageClient(aFwd, BUFFER_BRIDGE)
|
: ImageClient(aFwd, aFlags, BUFFER_BRIDGE)
|
||||||
, mAsyncContainerID(0)
|
, mAsyncContainerID(0)
|
||||||
, mLayer(nullptr)
|
, mLayer(nullptr)
|
||||||
{
|
{
|
||||||
|
|
|
@ -67,7 +67,8 @@ public:
|
||||||
virtual void FlushAllImages(bool aExceptFront) {}
|
virtual void FlushAllImages(bool aExceptFront) {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ImageClient(CompositableForwarder* aFwd, CompositableType aType);
|
ImageClient(CompositableForwarder* aFwd, TextureFlags aFlags,
|
||||||
|
CompositableType aType);
|
||||||
|
|
||||||
CompositableType mType;
|
CompositableType mType;
|
||||||
int32_t mLastPaintedImageSerial;
|
int32_t mLastPaintedImageSerial;
|
||||||
|
@ -90,10 +91,6 @@ public:
|
||||||
|
|
||||||
virtual bool AddTextureClient(TextureClient* aTexture) MOZ_OVERRIDE;
|
virtual bool AddTextureClient(TextureClient* aTexture) MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual TemporaryRef<BufferTextureClient>
|
|
||||||
CreateBufferTextureClient(gfx::SurfaceFormat aFormat,
|
|
||||||
TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT) MOZ_OVERRIDE;
|
|
||||||
|
|
||||||
virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE;
|
virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual already_AddRefed<Image> CreateImage(ImageFormat aFormat) MOZ_OVERRIDE;
|
virtual already_AddRefed<Image> CreateImage(ImageFormat aFormat) MOZ_OVERRIDE;
|
||||||
|
@ -105,9 +102,6 @@ protected:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
RefPtr<TextureClient> mFrontBuffer;
|
RefPtr<TextureClient> mFrontBuffer;
|
||||||
// Some layers may want to enforce some flags to all their textures
|
|
||||||
// (like disallowing tiling)
|
|
||||||
TextureFlags mTextureFlags;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -24,6 +24,25 @@
|
||||||
#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc
|
#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc
|
||||||
#include "ImageContainer.h" // for PlanarYCbCrImage, etc
|
#include "ImageContainer.h" // for PlanarYCbCrImage, etc
|
||||||
#include "mozilla/gfx/2D.h"
|
#include "mozilla/gfx/2D.h"
|
||||||
|
#include "mozilla/layers/TextureClientOGL.h"
|
||||||
|
|
||||||
|
#ifdef XP_WIN
|
||||||
|
#include "mozilla/layers/TextureD3D9.h"
|
||||||
|
#include "mozilla/layers/TextureD3D11.h"
|
||||||
|
#include "gfxWindowsPlatform.h"
|
||||||
|
#include "gfx2DGlue.h"
|
||||||
|
#endif
|
||||||
|
#ifdef MOZ_X11
|
||||||
|
#include "mozilla/layers/TextureClientX11.h"
|
||||||
|
#ifdef GL_PROVIDER_GLX
|
||||||
|
#include "GLXLibrary.h"
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MOZ_WIDGET_GONK
|
||||||
|
#include <cutils/properties.h>
|
||||||
|
#include "mozilla/layers/GrallocTextureClient.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef MOZ_ANDROID_OMTC
|
#ifdef MOZ_ANDROID_OMTC
|
||||||
# include "gfxReusableImageSurfaceWrapper.h"
|
# include "gfxReusableImageSurfaceWrapper.h"
|
||||||
|
@ -193,6 +212,120 @@ TextureClient::GetIPDLActor()
|
||||||
return mActor;
|
return mActor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MOZ_WIDGET_GONK
|
||||||
|
static bool
|
||||||
|
DisableGralloc(SurfaceFormat aFormat)
|
||||||
|
{
|
||||||
|
if (aFormat == gfx::SurfaceFormat::A8) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#if ANDROID_VERSION <= 15
|
||||||
|
static bool checkedDevice = false;
|
||||||
|
static bool disableGralloc = false;
|
||||||
|
|
||||||
|
if (!checkedDevice) {
|
||||||
|
char propValue[PROPERTY_VALUE_MAX];
|
||||||
|
property_get("ro.product.device", propValue, "None");
|
||||||
|
|
||||||
|
if (strcmp("crespo",propValue) == 0) {
|
||||||
|
NS_WARNING("Nexus S has issues with gralloc, falling back to shmem");
|
||||||
|
disableGralloc = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkedDevice = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (disableGralloc) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// static
|
||||||
|
TemporaryRef<TextureClient>
|
||||||
|
TextureClient::CreateTextureClientForDrawing(ISurfaceAllocator* aAllocator,
|
||||||
|
SurfaceFormat aFormat,
|
||||||
|
TextureFlags aTextureFlags)
|
||||||
|
{
|
||||||
|
RefPtr<TextureClient> result;
|
||||||
|
|
||||||
|
#ifdef XP_WIN
|
||||||
|
LayersBackend parentBackend = aAllocator->GetCompositorBackendType();
|
||||||
|
if (parentBackend == LayersBackend::LAYERS_D3D11 && gfxWindowsPlatform::GetPlatform()->GetD2DDevice() &&
|
||||||
|
!(aTextureFlags & TEXTURE_ALLOC_FALLBACK)) {
|
||||||
|
result = new TextureClientD3D11(aFormat, aTextureFlags);
|
||||||
|
}
|
||||||
|
if (parentBackend == LayersBackend::LAYERS_D3D9 &&
|
||||||
|
aAllocator->IsSameProcess() &&
|
||||||
|
!(aTextureFlags & TEXTURE_ALLOC_FALLBACK)) {
|
||||||
|
if (!gfxWindowsPlatform::GetPlatform()->GetD3D9Device()) {
|
||||||
|
result = new DIBTextureClientD3D9(aFormat, aTextureFlags);
|
||||||
|
} else {
|
||||||
|
result = new CairoTextureClientD3D9(aFormat, aTextureFlags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MOZ_X11
|
||||||
|
LayersBackend parentBackend = aAllocator->GetCompositorBackendType();
|
||||||
|
gfxSurfaceType type =
|
||||||
|
gfxPlatform::GetPlatform()->ScreenReferenceSurface()->GetType();
|
||||||
|
|
||||||
|
if (parentBackend == LayersBackend::LAYERS_BASIC &&
|
||||||
|
type == gfxSurfaceType::Xlib &&
|
||||||
|
!(aTextureFlags & TEXTURE_ALLOC_FALLBACK))
|
||||||
|
{
|
||||||
|
result = new TextureClientX11(aFormat, aTextureFlags);
|
||||||
|
}
|
||||||
|
#ifdef GL_PROVIDER_GLX
|
||||||
|
if (parentBackend == LayersBackend::LAYERS_OPENGL &&
|
||||||
|
type == gfxSurfaceType::Xlib &&
|
||||||
|
!(aTextureFlags & TEXTURE_ALLOC_FALLBACK) &&
|
||||||
|
aFormat != SurfaceFormat::A8 &&
|
||||||
|
gl::sGLXLibrary.UseTextureFromPixmap())
|
||||||
|
{
|
||||||
|
result = new TextureClientX11(aFormat, aTextureFlags);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MOZ_WIDGET_GONK
|
||||||
|
if (!DisableGralloc(aFormat)) {
|
||||||
|
result = new GrallocTextureClientOGL(aAllocator, aFormat, aTextureFlags);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Can't do any better than a buffer texture client.
|
||||||
|
if (!result) {
|
||||||
|
result = CreateBufferTextureClient(aAllocator, aFormat, aTextureFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(!result || result->AsTextureClientDrawTarget(),
|
||||||
|
"Not a TextureClientDrawTarget?");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
TemporaryRef<BufferTextureClient>
|
||||||
|
TextureClient::CreateBufferTextureClient(ISurfaceAllocator* aAllocator,
|
||||||
|
SurfaceFormat aFormat,
|
||||||
|
TextureFlags aTextureFlags)
|
||||||
|
{
|
||||||
|
if (gfxPlatform::GetPlatform()->PreferMemoryOverShmem()) {
|
||||||
|
RefPtr<BufferTextureClient> result = new MemoryTextureClient(aAllocator, aFormat,
|
||||||
|
aTextureFlags);
|
||||||
|
return result.forget();
|
||||||
|
}
|
||||||
|
RefPtr<BufferTextureClient> result = new ShmemTextureClient(aAllocator, aFormat,
|
||||||
|
aTextureFlags);
|
||||||
|
return result.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class ShmemTextureClientData : public TextureClientData
|
class ShmemTextureClientData : public TextureClientData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -296,6 +429,30 @@ void TextureClient::ForceRemove()
|
||||||
MarkInvalid();
|
MarkInvalid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TextureClient::CopyToTextureClient(TextureClient* aTarget,
|
||||||
|
const gfx::IntRect* aRect,
|
||||||
|
const gfx::IntPoint* aPoint)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsLocked());
|
||||||
|
MOZ_ASSERT(aTarget->IsLocked());
|
||||||
|
|
||||||
|
if (!aTarget->AsTextureClientDrawTarget() || !AsTextureClientDrawTarget()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<DrawTarget> destinationTarget = aTarget->AsTextureClientDrawTarget()->GetAsDrawTarget();
|
||||||
|
RefPtr<DrawTarget> sourceTarget = AsTextureClientDrawTarget()->GetAsDrawTarget();
|
||||||
|
RefPtr<gfx::SourceSurface> source = sourceTarget->Snapshot();
|
||||||
|
destinationTarget->CopySurface(source,
|
||||||
|
aRect ? *aRect : gfx::IntRect(gfx::IntPoint(0, 0), GetSize()),
|
||||||
|
aPoint ? *aPoint : gfx::IntPoint(0, 0));
|
||||||
|
destinationTarget = nullptr;
|
||||||
|
source = nullptr;
|
||||||
|
sourceTarget = nullptr;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TextureClient::Finalize()
|
TextureClient::Finalize()
|
||||||
{
|
{
|
||||||
|
@ -339,12 +496,6 @@ ShmemTextureClient::ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ISurfaceAllocator*
|
|
||||||
ShmemTextureClient::GetAllocator() const
|
|
||||||
{
|
|
||||||
return mCompositable->GetForwarder();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ShmemTextureClient::Allocate(uint32_t aSize)
|
ShmemTextureClient::Allocate(uint32_t aSize)
|
||||||
{
|
{
|
||||||
|
@ -371,10 +522,10 @@ ShmemTextureClient::GetBufferSize() const
|
||||||
return mShmem.Size<uint8_t>();
|
return mShmem.Size<uint8_t>();
|
||||||
}
|
}
|
||||||
|
|
||||||
ShmemTextureClient::ShmemTextureClient(CompositableClient* aCompositable,
|
ShmemTextureClient::ShmemTextureClient(ISurfaceAllocator* aAllocator,
|
||||||
gfx::SurfaceFormat aFormat,
|
gfx::SurfaceFormat aFormat,
|
||||||
TextureFlags aFlags)
|
TextureFlags aFlags)
|
||||||
: BufferTextureClient(aCompositable, aFormat, aFlags)
|
: BufferTextureClient(aAllocator, aFormat, aFlags)
|
||||||
, mAllocated(false)
|
, mAllocated(false)
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(ShmemTextureClient);
|
MOZ_COUNT_CTOR(ShmemTextureClient);
|
||||||
|
@ -386,7 +537,7 @@ ShmemTextureClient::~ShmemTextureClient()
|
||||||
if (ShouldDeallocateInDestructor()) {
|
if (ShouldDeallocateInDestructor()) {
|
||||||
// if the buffer has never been shared we must deallocate it or ir would
|
// if the buffer has never been shared we must deallocate it or ir would
|
||||||
// leak.
|
// leak.
|
||||||
mCompositable->GetForwarder()->DeallocShmem(mShmem);
|
GetAllocator()->DeallocShmem(mShmem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -417,10 +568,10 @@ MemoryTextureClient::Allocate(uint32_t aSize)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryTextureClient::MemoryTextureClient(CompositableClient* aCompositable,
|
MemoryTextureClient::MemoryTextureClient(ISurfaceAllocator* aAllocator,
|
||||||
gfx::SurfaceFormat aFormat,
|
gfx::SurfaceFormat aFormat,
|
||||||
TextureFlags aFlags)
|
TextureFlags aFlags)
|
||||||
: BufferTextureClient(aCompositable, aFormat, aFlags)
|
: BufferTextureClient(aAllocator, aFormat, aFlags)
|
||||||
, mBuffer(nullptr)
|
, mBuffer(nullptr)
|
||||||
, mBufSize(0)
|
, mBufSize(0)
|
||||||
{
|
{
|
||||||
|
@ -438,11 +589,11 @@ MemoryTextureClient::~MemoryTextureClient()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferTextureClient::BufferTextureClient(CompositableClient* aCompositable,
|
BufferTextureClient::BufferTextureClient(ISurfaceAllocator* aAllocator,
|
||||||
gfx::SurfaceFormat aFormat,
|
gfx::SurfaceFormat aFormat,
|
||||||
TextureFlags aFlags)
|
TextureFlags aFlags)
|
||||||
: TextureClient(aFlags)
|
: TextureClient(aFlags)
|
||||||
, mCompositable(aCompositable)
|
, mAllocator(aAllocator)
|
||||||
, mFormat(aFormat)
|
, mFormat(aFormat)
|
||||||
, mUsingFallbackDrawTarget(false)
|
, mUsingFallbackDrawTarget(false)
|
||||||
, mLocked(false)
|
, mLocked(false)
|
||||||
|
@ -451,6 +602,12 @@ BufferTextureClient::BufferTextureClient(CompositableClient* aCompositable,
|
||||||
BufferTextureClient::~BufferTextureClient()
|
BufferTextureClient::~BufferTextureClient()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
ISurfaceAllocator*
|
||||||
|
BufferTextureClient::GetAllocator() const
|
||||||
|
{
|
||||||
|
return mAllocator;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
BufferTextureClient::UpdateSurface(gfxASurface* aSurface)
|
BufferTextureClient::UpdateSurface(gfxASurface* aSurface)
|
||||||
{
|
{
|
||||||
|
|
|
@ -44,6 +44,7 @@ class PlanarYCbCrData;
|
||||||
class Image;
|
class Image;
|
||||||
class PTextureChild;
|
class PTextureChild;
|
||||||
class TextureChild;
|
class TextureChild;
|
||||||
|
class BufferTextureClient;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TextureClient is the abstraction that allows us to share data between the
|
* TextureClient is the abstraction that allows us to share data between the
|
||||||
|
@ -198,6 +199,16 @@ public:
|
||||||
TextureClient(TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT);
|
TextureClient(TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT);
|
||||||
virtual ~TextureClient();
|
virtual ~TextureClient();
|
||||||
|
|
||||||
|
static TemporaryRef<BufferTextureClient>
|
||||||
|
CreateBufferTextureClient(ISurfaceAllocator* aAllocator,
|
||||||
|
gfx::SurfaceFormat aFormat,
|
||||||
|
TextureFlags aTextureFlags);
|
||||||
|
|
||||||
|
static TemporaryRef<TextureClient>
|
||||||
|
CreateTextureClientForDrawing(ISurfaceAllocator* aAllocator,
|
||||||
|
gfx::SurfaceFormat aFormat,
|
||||||
|
TextureFlags aTextureFlags);
|
||||||
|
|
||||||
virtual TextureClientSurface* AsTextureClientSurface() { return nullptr; }
|
virtual TextureClientSurface* AsTextureClientSurface() { return nullptr; }
|
||||||
virtual TextureClientDrawTarget* AsTextureClientDrawTarget() { return nullptr; }
|
virtual TextureClientDrawTarget* AsTextureClientDrawTarget() { return nullptr; }
|
||||||
virtual TextureClientYCbCr* AsTextureClientYCbCr() { return nullptr; }
|
virtual TextureClientYCbCr* AsTextureClientYCbCr() { return nullptr; }
|
||||||
|
@ -214,6 +225,15 @@ public:
|
||||||
|
|
||||||
virtual bool IsLocked() const = 0;
|
virtual bool IsLocked() const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies a rectangle from this texture client to a position in aTarget.
|
||||||
|
* It is assumed that the necessary locks are in place; so this should at
|
||||||
|
* least have a read lock and aTarget should at least have a write lock.
|
||||||
|
*/
|
||||||
|
virtual bool CopyToTextureClient(TextureClient* aTarget,
|
||||||
|
const gfx::IntRect* aRect,
|
||||||
|
const gfx::IntPoint* aPoint);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this texture has a lock/unlock mechanism.
|
* Returns true if this texture has a lock/unlock mechanism.
|
||||||
* Textures that do not implement locking should be immutable or should
|
* Textures that do not implement locking should be immutable or should
|
||||||
|
@ -221,6 +241,13 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual bool ImplementsLocking() const { return false; }
|
virtual bool ImplementsLocking() const { return false; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether the TextureClient implementation is backed by an
|
||||||
|
* in-memory buffer. The consequence of this is that locking the
|
||||||
|
* TextureClient does not contend with locking the texture on the host side.
|
||||||
|
*/
|
||||||
|
virtual bool HasInternalBuffer() const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocate and deallocate a TextureChild actor.
|
* Allocate and deallocate a TextureChild actor.
|
||||||
*
|
*
|
||||||
|
@ -355,7 +382,7 @@ class BufferTextureClient : public TextureClient
|
||||||
, public TextureClientDrawTarget
|
, public TextureClientDrawTarget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BufferTextureClient(CompositableClient* aCompositable, gfx::SurfaceFormat aFormat,
|
BufferTextureClient(ISurfaceAllocator* aAllocator, gfx::SurfaceFormat aFormat,
|
||||||
TextureFlags aFlags);
|
TextureFlags aFlags);
|
||||||
|
|
||||||
virtual ~BufferTextureClient();
|
virtual ~BufferTextureClient();
|
||||||
|
@ -411,9 +438,13 @@ public:
|
||||||
|
|
||||||
virtual size_t GetBufferSize() const = 0;
|
virtual size_t GetBufferSize() const = 0;
|
||||||
|
|
||||||
|
virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return true; }
|
||||||
|
|
||||||
|
ISurfaceAllocator* GetAllocator() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
RefPtr<gfx::DrawTarget> mDrawTarget;
|
RefPtr<gfx::DrawTarget> mDrawTarget;
|
||||||
CompositableClient* mCompositable;
|
RefPtr<ISurfaceAllocator> mAllocator;
|
||||||
gfx::SurfaceFormat mFormat;
|
gfx::SurfaceFormat mFormat;
|
||||||
gfx::IntSize mSize;
|
gfx::IntSize mSize;
|
||||||
OpenMode mOpenMode;
|
OpenMode mOpenMode;
|
||||||
|
@ -428,7 +459,7 @@ protected:
|
||||||
class ShmemTextureClient : public BufferTextureClient
|
class ShmemTextureClient : public BufferTextureClient
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ShmemTextureClient(CompositableClient* aCompositable, gfx::SurfaceFormat aFormat,
|
ShmemTextureClient(ISurfaceAllocator* aAllocator, gfx::SurfaceFormat aFormat,
|
||||||
TextureFlags aFlags);
|
TextureFlags aFlags);
|
||||||
|
|
||||||
~ShmemTextureClient();
|
~ShmemTextureClient();
|
||||||
|
@ -445,13 +476,12 @@ public:
|
||||||
|
|
||||||
virtual TextureClientData* DropTextureData() MOZ_OVERRIDE;
|
virtual TextureClientData* DropTextureData() MOZ_OVERRIDE;
|
||||||
|
|
||||||
ISurfaceAllocator* GetAllocator() const;
|
virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return true; }
|
||||||
|
|
||||||
mozilla::ipc::Shmem& GetShmem() { return mShmem; }
|
mozilla::ipc::Shmem& GetShmem() { return mShmem; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
mozilla::ipc::Shmem mShmem;
|
mozilla::ipc::Shmem mShmem;
|
||||||
RefPtr<ISurfaceAllocator> mAllocator;
|
|
||||||
bool mAllocated;
|
bool mAllocated;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -463,7 +493,7 @@ protected:
|
||||||
class MemoryTextureClient : public BufferTextureClient
|
class MemoryTextureClient : public BufferTextureClient
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MemoryTextureClient(CompositableClient* aCompositable, gfx::SurfaceFormat aFormat,
|
MemoryTextureClient(ISurfaceAllocator* aAllocator, gfx::SurfaceFormat aFormat,
|
||||||
TextureFlags aFlags);
|
TextureFlags aFlags);
|
||||||
|
|
||||||
~MemoryTextureClient();
|
~MemoryTextureClient();
|
||||||
|
@ -478,6 +508,8 @@ public:
|
||||||
|
|
||||||
virtual bool IsAllocated() const MOZ_OVERRIDE { return mBuffer != nullptr; }
|
virtual bool IsAllocated() const MOZ_OVERRIDE { return mBuffer != nullptr; }
|
||||||
|
|
||||||
|
virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return true; }
|
||||||
|
|
||||||
virtual TextureClientData* DropTextureData() MOZ_OVERRIDE;
|
virtual TextureClientData* DropTextureData() MOZ_OVERRIDE;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -0,0 +1,146 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "TextureClientPool.h"
|
||||||
|
#include "CompositableClient.h"
|
||||||
|
#include "mozilla/layers/ISurfaceAllocator.h"
|
||||||
|
|
||||||
|
#include "gfxPrefs.h"
|
||||||
|
|
||||||
|
#include "nsComponentManagerUtils.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace layers {
|
||||||
|
|
||||||
|
static void
|
||||||
|
ShrinkCallback(nsITimer *aTimer, void *aClosure)
|
||||||
|
{
|
||||||
|
static_cast<TextureClientPool*>(aClosure)->ShrinkToMinimumSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureClientPool::TextureClientPool(gfx::SurfaceFormat aFormat, gfx::IntSize aSize,
|
||||||
|
ISurfaceAllocator *aAllocator)
|
||||||
|
: mFormat(aFormat)
|
||||||
|
, mSize(aSize)
|
||||||
|
, mOutstandingClients(0)
|
||||||
|
, mSurfaceAllocator(aAllocator)
|
||||||
|
{
|
||||||
|
mTimer = do_CreateInstance("@mozilla.org/timer;1");
|
||||||
|
}
|
||||||
|
|
||||||
|
TemporaryRef<TextureClient>
|
||||||
|
TextureClientPool::GetTextureClient()
|
||||||
|
{
|
||||||
|
mOutstandingClients++;
|
||||||
|
|
||||||
|
// Try to fetch a client from the pool
|
||||||
|
RefPtr<TextureClient> textureClient;
|
||||||
|
if (mTextureClients.size()) {
|
||||||
|
textureClient = mTextureClients.top();
|
||||||
|
mTextureClients.pop();
|
||||||
|
return textureClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We're increasing the number of outstanding TextureClients without reusing a
|
||||||
|
// client, we may need to free a deferred-return TextureClient.
|
||||||
|
ShrinkToMaximumSize();
|
||||||
|
|
||||||
|
// No unused clients in the pool, create one
|
||||||
|
if (gfxPrefs::ForceShmemTiles()) {
|
||||||
|
textureClient = TextureClient::CreateBufferTextureClient(mSurfaceAllocator, mFormat, TEXTURE_IMMEDIATE_UPLOAD);
|
||||||
|
} else {
|
||||||
|
textureClient = TextureClient::CreateTextureClientForDrawing(mSurfaceAllocator, mFormat, TEXTURE_IMMEDIATE_UPLOAD);
|
||||||
|
}
|
||||||
|
textureClient->AsTextureClientDrawTarget()->AllocateForSurface(mSize, ALLOC_DEFAULT);
|
||||||
|
|
||||||
|
return textureClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TextureClientPool::ReturnTextureClient(TextureClient *aClient)
|
||||||
|
{
|
||||||
|
if (!aClient) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MOZ_ASSERT(mOutstandingClients);
|
||||||
|
mOutstandingClients--;
|
||||||
|
|
||||||
|
// Add the client to the pool and shrink down if we're beyond our maximum size
|
||||||
|
mTextureClients.push(aClient);
|
||||||
|
ShrinkToMaximumSize();
|
||||||
|
|
||||||
|
// Kick off the pool shrinking timer if there are still more unused texture
|
||||||
|
// clients than our desired minimum cache size.
|
||||||
|
if (mTextureClients.size() > sMinCacheSize) {
|
||||||
|
mTimer->InitWithFuncCallback(ShrinkCallback, this, sShrinkTimeout,
|
||||||
|
nsITimer::TYPE_ONE_SHOT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TextureClientPool::ReturnTextureClientDeferred(TextureClient *aClient)
|
||||||
|
{
|
||||||
|
mTextureClientsDeferred.push(aClient);
|
||||||
|
ShrinkToMaximumSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TextureClientPool::ShrinkToMaximumSize()
|
||||||
|
{
|
||||||
|
uint32_t totalClientsOutstanding = mTextureClients.size() + mOutstandingClients;
|
||||||
|
|
||||||
|
// We're over our desired maximum size, immediately shrink down to the
|
||||||
|
// maximum, or zero if we have too many outstanding texture clients.
|
||||||
|
// We cull from the deferred TextureClients first, as we can't reuse those
|
||||||
|
// until they get returned.
|
||||||
|
while (totalClientsOutstanding > sMaxTextureClients) {
|
||||||
|
if (mTextureClientsDeferred.size()) {
|
||||||
|
mOutstandingClients--;
|
||||||
|
mTextureClientsDeferred.pop();
|
||||||
|
} else {
|
||||||
|
if (!mTextureClients.size()) {
|
||||||
|
// Getting here means we're over our desired number of TextureClients
|
||||||
|
// with none in the pool. This can happen for pathological cases, or
|
||||||
|
// it could mean that sMaxTextureClients needs adjusting for whatever
|
||||||
|
// device we're running on.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mTextureClients.pop();
|
||||||
|
}
|
||||||
|
totalClientsOutstanding--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TextureClientPool::ShrinkToMinimumSize()
|
||||||
|
{
|
||||||
|
while (mTextureClients.size() > sMinCacheSize) {
|
||||||
|
mTextureClients.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TextureClientPool::ReturnDeferredClients()
|
||||||
|
{
|
||||||
|
while (!mTextureClientsDeferred.empty()) {
|
||||||
|
ReturnTextureClient(mTextureClientsDeferred.top());
|
||||||
|
mTextureClientsDeferred.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TextureClientPool::Clear()
|
||||||
|
{
|
||||||
|
while (!mTextureClients.empty()) {
|
||||||
|
mTextureClients.pop();
|
||||||
|
}
|
||||||
|
while (!mTextureClientsDeferred.empty()) {
|
||||||
|
mOutstandingClients--;
|
||||||
|
mTextureClientsDeferred.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,107 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef MOZILLA_GFX_TEXTURECLIENTPOOL_H
|
||||||
|
#define MOZILLA_GFX_TEXTURECLIENTPOOL_H
|
||||||
|
|
||||||
|
#include "mozilla/gfx/Types.h"
|
||||||
|
#include "mozilla/gfx/Point.h"
|
||||||
|
#include "mozilla/RefPtr.h"
|
||||||
|
#include "TextureClient.h"
|
||||||
|
#include "nsITimer.h"
|
||||||
|
#include <stack>
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace layers {
|
||||||
|
|
||||||
|
class ISurfaceAllocator;
|
||||||
|
|
||||||
|
class TextureClientPool : public RefCounted<TextureClientPool>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MOZ_DECLARE_REFCOUNTED_TYPENAME(TextureClientPool)
|
||||||
|
TextureClientPool(gfx::SurfaceFormat aFormat, gfx::IntSize aSize,
|
||||||
|
ISurfaceAllocator *aAllocator);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an allocated TextureClient of size and format that are determined
|
||||||
|
* by the initialisation parameters given to the pool. This will either be
|
||||||
|
* a cached client that was returned to the pool, or a newly allocated
|
||||||
|
* client if one isn't available.
|
||||||
|
*
|
||||||
|
* All clients retrieved by this method should be returned using the return
|
||||||
|
* functions, or reported lost so that the pool can manage its size correctly.
|
||||||
|
*/
|
||||||
|
TemporaryRef<TextureClient> GetTextureClient();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a TextureClient that is no longer being used and is ready for
|
||||||
|
* immediate re-use or destruction.
|
||||||
|
*/
|
||||||
|
void ReturnTextureClient(TextureClient *aClient);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a TextureClient that is not yet ready to be reused, but will be
|
||||||
|
* imminently.
|
||||||
|
*/
|
||||||
|
void ReturnTextureClientDeferred(TextureClient *aClient);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to shrink the pool so that there are no more than
|
||||||
|
* sMaxTextureClients clients outstanding.
|
||||||
|
*/
|
||||||
|
void ShrinkToMaximumSize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to shrink the pool so that there are no more than sMinCacheSize
|
||||||
|
* unused clients.
|
||||||
|
*/
|
||||||
|
void ShrinkToMinimumSize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return any clients to the pool that were previously returned in
|
||||||
|
* ReturnTextureClientDeferred.
|
||||||
|
*/
|
||||||
|
void ReturnDeferredClients();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Report that a client retrieved via GetTextureClient() has become
|
||||||
|
* unusable, so that it will no longer be tracked.
|
||||||
|
*/
|
||||||
|
void ReportClientLost() { mOutstandingClients--; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calling this will cause the pool to attempt to relinquish any unused
|
||||||
|
* clients.
|
||||||
|
*/
|
||||||
|
void Clear();
|
||||||
|
|
||||||
|
private:
|
||||||
|
// The time in milliseconds before the pool will be shrunk to the minimum
|
||||||
|
// size after returning a client.
|
||||||
|
static const uint32_t sShrinkTimeout = 1000;
|
||||||
|
|
||||||
|
// The minimum size of the pool (the number of tiles that will be kept after
|
||||||
|
// shrinking).
|
||||||
|
static const uint32_t sMinCacheSize = 0;
|
||||||
|
|
||||||
|
// The maximum number of texture clients managed by this pool that we want
|
||||||
|
// to remain active.
|
||||||
|
static const uint32_t sMaxTextureClients = 50;
|
||||||
|
|
||||||
|
gfx::SurfaceFormat mFormat;
|
||||||
|
gfx::IntSize mSize;
|
||||||
|
|
||||||
|
uint32_t mOutstandingClients;
|
||||||
|
|
||||||
|
std::stack<RefPtr<TextureClient> > mTextureClients;
|
||||||
|
std::stack<RefPtr<TextureClient> > mTextureClientsDeferred;
|
||||||
|
nsRefPtr<nsITimer> mTimer;
|
||||||
|
RefPtr<ISurfaceAllocator> mSurfaceAllocator;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* MOZILLA_GFX_TEXTURECLIENTPOOL_H */
|
|
@ -18,6 +18,7 @@
|
||||||
#include "mozilla/gfx/Rect.h" // for Rect
|
#include "mozilla/gfx/Rect.h" // for Rect
|
||||||
#include "mozilla/layers/CompositableForwarder.h"
|
#include "mozilla/layers/CompositableForwarder.h"
|
||||||
#include "mozilla/layers/ShadowLayers.h" // for ShadowLayerForwarder
|
#include "mozilla/layers/ShadowLayers.h" // for ShadowLayerForwarder
|
||||||
|
#include "TextureClientPool.h"
|
||||||
#include "nsDebug.h" // for NS_ASSERTION
|
#include "nsDebug.h" // for NS_ASSERTION
|
||||||
#include "nsISupportsImpl.h" // for gfxContext::AddRef, etc
|
#include "nsISupportsImpl.h" // for gfxContext::AddRef, etc
|
||||||
#include "nsSize.h" // for nsIntSize
|
#include "nsSize.h" // for nsIntSize
|
||||||
|
@ -25,18 +26,23 @@
|
||||||
#include "nsMathUtils.h" // for NS_roundf
|
#include "nsMathUtils.h" // for NS_roundf
|
||||||
#include "gfx2DGlue.h"
|
#include "gfx2DGlue.h"
|
||||||
|
|
||||||
|
// This is the minimum area that we deem reasonable to copy from the front buffer to the
|
||||||
|
// back buffer on tile updates. If the valid region is smaller than this, we just
|
||||||
|
// redraw it and save on the copy (and requisite surface-locking involved).
|
||||||
|
#define MINIMUM_TILE_COPY_AREA ((TILEDLAYERBUFFER_TILE_SIZE * TILEDLAYERBUFFER_TILE_SIZE)/16)
|
||||||
|
|
||||||
#ifdef GFX_TILEDLAYER_DEBUG_OVERLAY
|
#ifdef GFX_TILEDLAYER_DEBUG_OVERLAY
|
||||||
#include "cairo.h"
|
#include "cairo.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
using mozilla::layers::Layer;
|
using mozilla::layers::Layer;
|
||||||
static void DrawDebugOverlay(gfxASurface* imgSurf, int x, int y)
|
static void DrawDebugOverlay(mozilla::gfx::DrawTarget* dt, int x, int y, int width, int height)
|
||||||
{
|
{
|
||||||
gfxContext c(imgSurf);
|
gfxContext c(dt);
|
||||||
|
|
||||||
// Draw border
|
// Draw border
|
||||||
c.NewPath();
|
c.NewPath();
|
||||||
c.SetDeviceColor(gfxRGBA(0.0, 0.0, 0.0, 1.0));
|
c.SetDeviceColor(gfxRGBA(0.0, 0.0, 0.0, 1.0));
|
||||||
c.Rectangle(gfxRect(gfxPoint(0,0),imgSurf->GetSize()));
|
c.Rectangle(gfxRect(0, 0, width, height));
|
||||||
c.Stroke();
|
c.Stroke();
|
||||||
|
|
||||||
// Build tile description
|
// Build tile description
|
||||||
|
@ -79,28 +85,37 @@ namespace layers {
|
||||||
TiledContentClient::TiledContentClient(ClientTiledThebesLayer* aThebesLayer,
|
TiledContentClient::TiledContentClient(ClientTiledThebesLayer* aThebesLayer,
|
||||||
ClientLayerManager* aManager)
|
ClientLayerManager* aManager)
|
||||||
: CompositableClient(aManager->AsShadowForwarder())
|
: CompositableClient(aManager->AsShadowForwarder())
|
||||||
, mTiledBuffer(aThebesLayer, aManager, &mSharedFrameMetricsHelper)
|
|
||||||
, mLowPrecisionTiledBuffer(aThebesLayer, aManager, &mSharedFrameMetricsHelper)
|
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(TiledContentClient);
|
MOZ_COUNT_CTOR(TiledContentClient);
|
||||||
|
|
||||||
// The preference is int in "thousands", so adjust:
|
mTiledBuffer = ClientTiledLayerBuffer(aThebesLayer, this, aManager,
|
||||||
|
&mSharedFrameMetricsHelper);
|
||||||
|
mLowPrecisionTiledBuffer = ClientTiledLayerBuffer(aThebesLayer, this, aManager,
|
||||||
|
&mSharedFrameMetricsHelper);
|
||||||
|
|
||||||
mLowPrecisionTiledBuffer.SetResolution(gfxPrefs::LowPrecisionResolution()/1000.f);
|
mLowPrecisionTiledBuffer.SetResolution(gfxPrefs::LowPrecisionResolution()/1000.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TiledContentClient::LockCopyAndWrite(TiledBufferType aType)
|
TiledContentClient::ClearCachedResources()
|
||||||
{
|
{
|
||||||
BasicTiledLayerBuffer* buffer = aType == LOW_PRECISION_TILED_BUFFER
|
mTiledBuffer.DiscardBackBuffers();
|
||||||
|
mLowPrecisionTiledBuffer.DiscardBackBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TiledContentClient::UseTiledLayerBuffer(TiledBufferType aType)
|
||||||
|
{
|
||||||
|
ClientTiledLayerBuffer* buffer = aType == LOW_PRECISION_TILED_BUFFER
|
||||||
? &mLowPrecisionTiledBuffer
|
? &mLowPrecisionTiledBuffer
|
||||||
: &mTiledBuffer;
|
: &mTiledBuffer;
|
||||||
|
|
||||||
// Take an extra ReadLock on behalf of the TiledContentHost. This extra
|
// Take a ReadLock on behalf of the TiledContentHost. This
|
||||||
// reference will be adopted when the descriptor is opened by
|
// reference will be adopted when the descriptor is opened in
|
||||||
// BasicTiledLayerTile::OpenDescriptor.
|
// TiledLayerBufferComposite.
|
||||||
buffer->ReadLock();
|
buffer->ReadLock();
|
||||||
|
|
||||||
mForwarder->PaintedTiledLayerBuffer(this, buffer->GetSurfaceDescriptorTiles());
|
mForwarder->UseTiledLayerBuffer(this, buffer->GetSurfaceDescriptorTiles());
|
||||||
buffer->ClearPaintedRegion();
|
buffer->ClearPaintedRegion();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,10 +244,12 @@ SharedFrameMetricsHelper::AboutToCheckerboard(const FrameMetrics& aContentMetric
|
||||||
return !aContentMetrics.mDisplayPort.Contains(aCompositorMetrics.CalculateCompositedRectInCssPixels() - aCompositorMetrics.mScrollOffset);
|
return !aContentMetrics.mDisplayPort.Contains(aCompositorMetrics.CalculateCompositedRectInCssPixels() - aCompositorMetrics.mScrollOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicTiledLayerBuffer::BasicTiledLayerBuffer(ClientTiledThebesLayer* aThebesLayer,
|
ClientTiledLayerBuffer::ClientTiledLayerBuffer(ClientTiledThebesLayer* aThebesLayer,
|
||||||
|
CompositableClient* aCompositableClient,
|
||||||
ClientLayerManager* aManager,
|
ClientLayerManager* aManager,
|
||||||
SharedFrameMetricsHelper* aHelper)
|
SharedFrameMetricsHelper* aHelper)
|
||||||
: mThebesLayer(aThebesLayer)
|
: mThebesLayer(aThebesLayer)
|
||||||
|
, mCompositableClient(aCompositableClient)
|
||||||
, mManager(aManager)
|
, mManager(aManager)
|
||||||
, mLastPaintOpaque(false)
|
, mLastPaintOpaque(false)
|
||||||
, mSharedFrameMetricsHelper(aHelper)
|
, mSharedFrameMetricsHelper(aHelper)
|
||||||
|
@ -240,14 +257,14 @@ BasicTiledLayerBuffer::BasicTiledLayerBuffer(ClientTiledThebesLayer* aThebesLaye
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
BasicTiledLayerBuffer::HasFormatChanged() const
|
ClientTiledLayerBuffer::HasFormatChanged() const
|
||||||
{
|
{
|
||||||
return mThebesLayer->CanUseOpaqueSurface() != mLastPaintOpaque;
|
return mThebesLayer->CanUseOpaqueSurface() != mLastPaintOpaque;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gfxContentType
|
gfxContentType
|
||||||
BasicTiledLayerBuffer::GetContentType() const
|
ClientTiledLayerBuffer::GetContentType() const
|
||||||
{
|
{
|
||||||
if (mThebesLayer->CanUseOpaqueSurface()) {
|
if (mThebesLayer->CanUseOpaqueSurface()) {
|
||||||
return gfxContentType::COLOR;
|
return gfxContentType::COLOR;
|
||||||
|
@ -256,54 +273,311 @@ BasicTiledLayerBuffer::GetContentType() const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gfxMemorySharedReadLock::gfxMemorySharedReadLock()
|
||||||
|
: mReadCount(1)
|
||||||
|
{
|
||||||
|
MOZ_COUNT_CTOR(gfxMemorySharedReadLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
gfxMemorySharedReadLock::~gfxMemorySharedReadLock()
|
||||||
|
{
|
||||||
|
MOZ_COUNT_DTOR(gfxMemorySharedReadLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t
|
||||||
|
gfxMemorySharedReadLock::ReadLock()
|
||||||
|
{
|
||||||
|
NS_ASSERT_OWNINGTHREAD(gfxMemorySharedReadLock);
|
||||||
|
|
||||||
|
return PR_ATOMIC_INCREMENT(&mReadCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t
|
||||||
|
gfxMemorySharedReadLock::ReadUnlock()
|
||||||
|
{
|
||||||
|
int32_t readCount = PR_ATOMIC_DECREMENT(&mReadCount);
|
||||||
|
NS_ASSERTION(readCount >= 0, "ReadUnlock called without ReadLock.");
|
||||||
|
|
||||||
|
return readCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t
|
||||||
|
gfxMemorySharedReadLock::GetReadCount()
|
||||||
|
{
|
||||||
|
NS_ASSERT_OWNINGTHREAD(gfxMemorySharedReadLock);
|
||||||
|
return mReadCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
gfxShmSharedReadLock::gfxShmSharedReadLock(ISurfaceAllocator* aAllocator)
|
||||||
|
: mAllocator(aAllocator)
|
||||||
|
{
|
||||||
|
MOZ_COUNT_CTOR(gfxShmSharedReadLock);
|
||||||
|
|
||||||
|
if (mAllocator) {
|
||||||
|
#define MOZ_ALIGN_WORD(x) (((x) + 3) & ~3)
|
||||||
|
if (mAllocator->AllocUnsafeShmem(MOZ_ALIGN_WORD(sizeof(ShmReadLockInfo)),
|
||||||
|
mozilla::ipc::SharedMemory::TYPE_BASIC, &mShmem)) {
|
||||||
|
ShmReadLockInfo* info = GetShmReadLockInfoPtr();
|
||||||
|
info->readCount = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gfxShmSharedReadLock::~gfxShmSharedReadLock()
|
||||||
|
{
|
||||||
|
MOZ_COUNT_DTOR(gfxShmSharedReadLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t
|
||||||
|
gfxShmSharedReadLock::ReadLock() {
|
||||||
|
NS_ASSERT_OWNINGTHREAD(gfxShmSharedReadLock);
|
||||||
|
|
||||||
|
ShmReadLockInfo* info = GetShmReadLockInfoPtr();
|
||||||
|
return PR_ATOMIC_INCREMENT(&info->readCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t
|
||||||
|
gfxShmSharedReadLock::ReadUnlock() {
|
||||||
|
ShmReadLockInfo* info = GetShmReadLockInfoPtr();
|
||||||
|
int32_t readCount = PR_ATOMIC_DECREMENT(&info->readCount);
|
||||||
|
NS_ASSERTION(readCount >= 0, "ReadUnlock called without a ReadLock.");
|
||||||
|
if (readCount <= 0) {
|
||||||
|
mAllocator->DeallocShmem(mShmem);
|
||||||
|
}
|
||||||
|
return readCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t
|
||||||
|
gfxShmSharedReadLock::GetReadCount() {
|
||||||
|
NS_ASSERT_OWNINGTHREAD(gfxShmSharedReadLock);
|
||||||
|
|
||||||
|
ShmReadLockInfo* info = GetShmReadLockInfoPtr();
|
||||||
|
return info->readCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Placeholder
|
||||||
|
TileClient::TileClient()
|
||||||
|
: mBackBuffer(nullptr)
|
||||||
|
, mFrontBuffer(nullptr)
|
||||||
|
, mBackLock(nullptr)
|
||||||
|
, mFrontLock(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
TileClient::TileClient(const TileClient& o)
|
||||||
|
{
|
||||||
|
mBackBuffer = o.mBackBuffer;
|
||||||
|
mFrontBuffer = o.mFrontBuffer;
|
||||||
|
mBackLock = o.mBackLock;
|
||||||
|
mFrontLock = o.mFrontLock;
|
||||||
|
#ifdef GFX_TILEDLAYER_DEBUG_OVERLAY
|
||||||
|
mLastUpdate = o.mLastUpdate;
|
||||||
|
#endif
|
||||||
|
mManager = o.mManager;
|
||||||
|
mInvalidFront = o.mInvalidFront;
|
||||||
|
mInvalidBack = o.mInvalidBack;
|
||||||
|
}
|
||||||
|
|
||||||
|
TileClient&
|
||||||
|
TileClient::operator=(const TileClient& o)
|
||||||
|
{
|
||||||
|
if (this == &o) return *this;
|
||||||
|
mBackBuffer = o.mBackBuffer;
|
||||||
|
mFrontBuffer = o.mFrontBuffer;
|
||||||
|
mBackLock = o.mBackLock;
|
||||||
|
mFrontLock = o.mFrontLock;
|
||||||
|
#ifdef GFX_TILEDLAYER_DEBUG_OVERLAY
|
||||||
|
mLastUpdate = o.mLastUpdate;
|
||||||
|
#endif
|
||||||
|
mManager = o.mManager;
|
||||||
|
mInvalidFront = o.mInvalidFront;
|
||||||
|
mInvalidBack = o.mInvalidBack;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
TileClient::Flip()
|
||||||
|
{
|
||||||
|
RefPtr<TextureClient> frontBuffer = mFrontBuffer;
|
||||||
|
mFrontBuffer = mBackBuffer;
|
||||||
|
mBackBuffer = frontBuffer;
|
||||||
|
RefPtr<gfxSharedReadLock> frontLock = mFrontLock;
|
||||||
|
mFrontLock = mBackLock;
|
||||||
|
mBackLock = frontLock;
|
||||||
|
nsIntRegion invalidFront = mInvalidFront;
|
||||||
|
mInvalidFront = mInvalidBack;
|
||||||
|
mInvalidBack = invalidFront;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TileClient::ValidateBackBufferFromFront(const nsIntRegion& aDirtyRegion,
|
||||||
|
bool aCanRerasterizeValidRegion)
|
||||||
|
{
|
||||||
|
if (mBackBuffer && mFrontBuffer) {
|
||||||
|
const nsIntRect tileRect = nsIntRect(0, 0, TILEDLAYERBUFFER_TILE_SIZE, TILEDLAYERBUFFER_TILE_SIZE);
|
||||||
|
|
||||||
|
if (aDirtyRegion.Contains(tileRect)) {
|
||||||
|
// The dirty region means that we no longer need the front buffer, so
|
||||||
|
// discard it.
|
||||||
|
DiscardFrontBuffer();
|
||||||
|
} else {
|
||||||
|
// Region that needs copying.
|
||||||
|
nsIntRegion regionToCopy = mInvalidBack;
|
||||||
|
|
||||||
|
regionToCopy.Sub(regionToCopy, aDirtyRegion);
|
||||||
|
|
||||||
|
if (regionToCopy.IsEmpty() ||
|
||||||
|
(aCanRerasterizeValidRegion &&
|
||||||
|
regionToCopy.Area() < MINIMUM_TILE_COPY_AREA)) {
|
||||||
|
// Just redraw it all.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mFrontBuffer->Lock(OPEN_READ)) {
|
||||||
|
NS_WARNING("Failed to lock the tile's front buffer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
TextureClientAutoUnlock autoFront(mFrontBuffer);
|
||||||
|
|
||||||
|
if (!mBackBuffer->Lock(OPEN_WRITE)) {
|
||||||
|
NS_WARNING("Failed to lock the tile's back buffer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
TextureClientAutoUnlock autoBack(mBackBuffer);
|
||||||
|
|
||||||
|
// Copy the bounding rect of regionToCopy. As tiles are quite small, it
|
||||||
|
// is unlikely that we'd save much by copying each individual rect of the
|
||||||
|
// region, but we can reevaluate this if it becomes an issue.
|
||||||
|
const nsIntRect rectToCopy = regionToCopy.GetBounds();
|
||||||
|
gfx::IntRect gfxRectToCopy(rectToCopy.x, rectToCopy.y, rectToCopy.width, rectToCopy.height);
|
||||||
|
gfx::IntPoint gfxRectToCopyTopLeft = gfxRectToCopy.TopLeft();
|
||||||
|
mFrontBuffer->CopyToTextureClient(mBackBuffer, &gfxRectToCopy, &gfxRectToCopyTopLeft);
|
||||||
|
|
||||||
|
mInvalidBack.SetEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TileClient::DiscardFrontBuffer()
|
||||||
|
{
|
||||||
|
if (mFrontBuffer) {
|
||||||
|
MOZ_ASSERT(mFrontLock);
|
||||||
|
mManager->GetTexturePool(mFrontBuffer->AsTextureClientDrawTarget()->GetFormat())->ReturnTextureClientDeferred(mFrontBuffer);
|
||||||
|
mFrontLock->ReadUnlock();
|
||||||
|
mFrontBuffer = nullptr;
|
||||||
|
mFrontLock = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TileClient::DiscardBackBuffer()
|
||||||
|
{
|
||||||
|
if (mBackBuffer) {
|
||||||
|
MOZ_ASSERT(mBackLock);
|
||||||
|
mManager->GetTexturePool(mBackBuffer->AsTextureClientDrawTarget()->GetFormat())->ReturnTextureClient(mBackBuffer);
|
||||||
|
mBackLock->ReadUnlock();
|
||||||
|
mBackBuffer = nullptr;
|
||||||
|
mBackLock = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureClient*
|
||||||
|
TileClient::GetBackBuffer(const nsIntRegion& aDirtyRegion, TextureClientPool *aPool, bool *aCreatedTextureClient, bool aCanRerasterizeValidRegion)
|
||||||
|
{
|
||||||
|
// Try to re-use the front-buffer if possible
|
||||||
|
if (mFrontBuffer &&
|
||||||
|
mFrontBuffer->HasInternalBuffer() &&
|
||||||
|
mFrontLock->GetReadCount() == 1) {
|
||||||
|
// If we had a backbuffer we no longer care about it since we'll
|
||||||
|
// re-use the front buffer.
|
||||||
|
DiscardBackBuffer();
|
||||||
|
Flip();
|
||||||
|
return mBackBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mBackBuffer ||
|
||||||
|
mBackLock->GetReadCount() > 1) {
|
||||||
|
if (mBackBuffer) {
|
||||||
|
// Our current back-buffer is still locked by the compositor. This can occur
|
||||||
|
// when the client is producing faster than the compositor can consume. In
|
||||||
|
// this case we just want to drop it and not return it to the pool.
|
||||||
|
aPool->ReportClientLost();
|
||||||
|
}
|
||||||
|
mBackBuffer = aPool->GetTextureClient();
|
||||||
|
// Create a lock for our newly created back-buffer.
|
||||||
|
if (gfxPlatform::GetPlatform()->PreferMemoryOverShmem()) {
|
||||||
|
// If our compositor is in the same process, we can save some cycles by not
|
||||||
|
// using shared memory.
|
||||||
|
mBackLock = new gfxMemorySharedReadLock();
|
||||||
|
} else {
|
||||||
|
mBackLock = new gfxShmSharedReadLock(mManager->AsShadowForwarder());
|
||||||
|
}
|
||||||
|
*aCreatedTextureClient = true;
|
||||||
|
mInvalidBack = nsIntRect(0, 0, TILEDLAYERBUFFER_TILE_SIZE, TILEDLAYERBUFFER_TILE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ValidateBackBufferFromFront(aDirtyRegion, aCanRerasterizeValidRegion);
|
||||||
|
|
||||||
|
return mBackBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
TileDescriptor
|
TileDescriptor
|
||||||
BasicTiledLayerTile::GetTileDescriptor()
|
TileClient::GetTileDescriptor()
|
||||||
{
|
{
|
||||||
gfxReusableSurfaceWrapper* surface = GetSurface();
|
if (IsPlaceholderTile()) {
|
||||||
switch (surface->GetType()) {
|
|
||||||
case gfxReusableSurfaceWrapper::TYPE_IMAGE :
|
|
||||||
return BasicTileDescriptor(uintptr_t(surface));
|
|
||||||
|
|
||||||
case gfxReusableSurfaceWrapper::TYPE_SHARED_IMAGE :
|
|
||||||
return BasicShmTileDescriptor(static_cast<gfxReusableSharedImageSurfaceWrapper*>(surface)->GetShmem());
|
|
||||||
|
|
||||||
default :
|
|
||||||
NS_NOTREACHED("Unhandled gfxReusableSurfaceWrapper type");
|
|
||||||
return PlaceholderTileDescriptor();
|
return PlaceholderTileDescriptor();
|
||||||
}
|
}
|
||||||
|
MOZ_ASSERT(mFrontLock);
|
||||||
|
if (mFrontLock->GetType() == gfxSharedReadLock::TYPE_MEMORY) {
|
||||||
|
// AddRef here and Release when receiving on the host side to make sure the
|
||||||
|
// reference count doesn't go to zero before the host receives the message.
|
||||||
|
// see TiledLayerBufferComposite::TiledLayerBufferComposite
|
||||||
|
mFrontLock->AddRef();
|
||||||
|
}
|
||||||
|
return TexturedTileDescriptor(nullptr, mFrontBuffer->GetIPDLActor(),
|
||||||
|
mFrontLock->GetType() == gfxSharedReadLock::TYPE_MEMORY
|
||||||
|
? TileLock(uintptr_t(mFrontLock.get()))
|
||||||
|
: TileLock(static_cast<gfxShmSharedReadLock*>(mFrontLock.get())->GetShmem()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ClientTiledLayerBuffer::ReadUnlock() {
|
||||||
|
for (size_t i = 0; i < mRetainedTiles.Length(); i++) {
|
||||||
|
if (mRetainedTiles[i].IsPlaceholderTile()) continue;
|
||||||
|
mRetainedTiles[i].ReadUnlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* static */ BasicTiledLayerTile
|
void
|
||||||
BasicTiledLayerTile::OpenDescriptor(ISurfaceAllocator *aAllocator, const TileDescriptor& aDesc)
|
ClientTiledLayerBuffer::ReadLock() {
|
||||||
|
for (size_t i = 0; i < mRetainedTiles.Length(); i++) {
|
||||||
|
if (mRetainedTiles[i].IsPlaceholderTile()) continue;
|
||||||
|
mRetainedTiles[i].ReadLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ClientTiledLayerBuffer::Release()
|
||||||
{
|
{
|
||||||
switch (aDesc.type()) {
|
for (size_t i = 0; i < mRetainedTiles.Length(); i++) {
|
||||||
case TileDescriptor::TBasicShmTileDescriptor : {
|
if (mRetainedTiles[i].IsPlaceholderTile()) continue;
|
||||||
nsRefPtr<gfxReusableSurfaceWrapper> surface =
|
mRetainedTiles[i].Release();
|
||||||
gfxReusableSharedImageSurfaceWrapper::Open(
|
}
|
||||||
aAllocator, aDesc.get_BasicShmTileDescriptor().reusableSurface());
|
|
||||||
return BasicTiledLayerTile(
|
|
||||||
new DeprecatedTextureClientTile(nullptr, TextureInfo(BUFFER_TILED), surface));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case TileDescriptor::TBasicTileDescriptor : {
|
void
|
||||||
nsRefPtr<gfxReusableSurfaceWrapper> surface =
|
ClientTiledLayerBuffer::DiscardBackBuffers()
|
||||||
reinterpret_cast<gfxReusableSurfaceWrapper*>(
|
{
|
||||||
aDesc.get_BasicTileDescriptor().reusableSurface());
|
for (size_t i = 0; i < mRetainedTiles.Length(); i++) {
|
||||||
surface->ReadUnlock();
|
if (mRetainedTiles[i].IsPlaceholderTile()) continue;
|
||||||
return BasicTiledLayerTile(
|
mRetainedTiles[i].DiscardBackBuffer();
|
||||||
new DeprecatedTextureClientTile(nullptr, TextureInfo(BUFFER_TILED), surface));
|
|
||||||
}
|
|
||||||
|
|
||||||
default :
|
|
||||||
NS_NOTREACHED("Unknown tile descriptor type!");
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SurfaceDescriptorTiles
|
SurfaceDescriptorTiles
|
||||||
BasicTiledLayerBuffer::GetSurfaceDescriptorTiles()
|
ClientTiledLayerBuffer::GetSurfaceDescriptorTiles()
|
||||||
{
|
{
|
||||||
InfallibleTArray<TileDescriptor> tiles;
|
InfallibleTArray<TileDescriptor> tiles;
|
||||||
|
|
||||||
|
@ -321,23 +595,8 @@ BasicTiledLayerBuffer::GetSurfaceDescriptorTiles()
|
||||||
mResolution);
|
mResolution);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ BasicTiledLayerBuffer
|
|
||||||
BasicTiledLayerBuffer::OpenDescriptor(ISurfaceAllocator *aAllocator,
|
|
||||||
const SurfaceDescriptorTiles& aDescriptor,
|
|
||||||
SharedFrameMetricsHelper* aHelper)
|
|
||||||
{
|
|
||||||
return BasicTiledLayerBuffer(aAllocator,
|
|
||||||
aDescriptor.validRegion(),
|
|
||||||
aDescriptor.paintedRegion(),
|
|
||||||
aDescriptor.tiles(),
|
|
||||||
aDescriptor.retainedWidth(),
|
|
||||||
aDescriptor.retainedHeight(),
|
|
||||||
aDescriptor.resolution(),
|
|
||||||
aHelper);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BasicTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
|
ClientTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
|
||||||
const nsIntRegion& aPaintRegion,
|
const nsIntRegion& aPaintRegion,
|
||||||
LayerManager::DrawThebesLayerCallback aCallback,
|
LayerManager::DrawThebesLayerCallback aCallback,
|
||||||
void* aCallbackData)
|
void* aCallbackData)
|
||||||
|
@ -371,12 +630,11 @@ BasicTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
|
||||||
|
|
||||||
const nsIntRect bounds = aPaintRegion.GetBounds();
|
const nsIntRect bounds = aPaintRegion.GetBounds();
|
||||||
{
|
{
|
||||||
PROFILER_LABEL("BasicTiledLayerBuffer", "PaintThebesSingleBufferAlloc");
|
PROFILER_LABEL("ClientTiledLayerBuffer", "PaintThebesSingleBufferAlloc");
|
||||||
gfxImageFormat format =
|
gfxImageFormat format =
|
||||||
gfxPlatform::GetPlatform()->OptimalFormatForContent(
|
gfxPlatform::GetPlatform()->OptimalFormatForContent(
|
||||||
GetContentType());
|
GetContentType());
|
||||||
|
|
||||||
if (gfxPlatform::GetPlatform()->SupportsAzureContent()) {
|
|
||||||
mSinglePaintDrawTarget =
|
mSinglePaintDrawTarget =
|
||||||
gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
|
gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
|
||||||
gfx::IntSize(ceilf(bounds.width * mResolution),
|
gfx::IntSize(ceilf(bounds.width * mResolution),
|
||||||
|
@ -384,14 +642,6 @@ BasicTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
|
||||||
gfx::ImageFormatToSurfaceFormat(format));
|
gfx::ImageFormatToSurfaceFormat(format));
|
||||||
|
|
||||||
ctxt = new gfxContext(mSinglePaintDrawTarget);
|
ctxt = new gfxContext(mSinglePaintDrawTarget);
|
||||||
} else {
|
|
||||||
mSinglePaintBuffer = new gfxImageSurface(
|
|
||||||
gfxIntSize(ceilf(bounds.width * mResolution),
|
|
||||||
ceilf(bounds.height * mResolution)),
|
|
||||||
format,
|
|
||||||
!mThebesLayer->CanUseOpaqueSurface());
|
|
||||||
ctxt = new gfxContext(mSinglePaintBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
mSinglePaintBufferOffset = nsIntPoint(bounds.x, bounds.y);
|
mSinglePaintBufferOffset = nsIntPoint(bounds.x, bounds.y);
|
||||||
}
|
}
|
||||||
|
@ -404,7 +654,7 @@ BasicTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
|
||||||
}
|
}
|
||||||
start = PR_IntervalNow();
|
start = PR_IntervalNow();
|
||||||
#endif
|
#endif
|
||||||
PROFILER_LABEL("BasicTiledLayerBuffer", "PaintThebesSingleBufferDraw");
|
PROFILER_LABEL("ClientTiledLayerBuffer", "PaintThebesSingleBufferDraw");
|
||||||
|
|
||||||
mCallback(mThebesLayer, ctxt, aPaintRegion, DrawRegionClip::CLIP_NONE, nsIntRegion(), mCallbackData);
|
mCallback(mThebesLayer, ctxt, aPaintRegion, DrawRegionClip::CLIP_NONE, nsIntRegion(), mCallbackData);
|
||||||
}
|
}
|
||||||
|
@ -424,7 +674,7 @@ BasicTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
|
||||||
start = PR_IntervalNow();
|
start = PR_IntervalNow();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PROFILER_LABEL("BasicTiledLayerBuffer", "PaintThebesUpdate");
|
PROFILER_LABEL("ClientTiledLayerBuffer", "PaintThebesUpdate");
|
||||||
Update(aNewValidRegion, aPaintRegion);
|
Update(aNewValidRegion, aPaintRegion);
|
||||||
|
|
||||||
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
|
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
|
||||||
|
@ -437,102 +687,15 @@ BasicTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
|
||||||
mLastPaintOpaque = mThebesLayer->CanUseOpaqueSurface();
|
mLastPaintOpaque = mThebesLayer->CanUseOpaqueSurface();
|
||||||
mCallback = nullptr;
|
mCallback = nullptr;
|
||||||
mCallbackData = nullptr;
|
mCallbackData = nullptr;
|
||||||
mSinglePaintBuffer = nullptr;
|
|
||||||
mSinglePaintDrawTarget = nullptr;
|
mSinglePaintDrawTarget = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicTiledLayerTile
|
TileClient
|
||||||
BasicTiledLayerBuffer::ValidateTileInternal(BasicTiledLayerTile aTile,
|
ClientTiledLayerBuffer::ValidateTile(TileClient aTile,
|
||||||
const nsIntPoint& aTileOrigin,
|
|
||||||
const nsIntRect& aDirtyRect)
|
|
||||||
{
|
|
||||||
if (aTile.IsPlaceholderTile()) {
|
|
||||||
RefPtr<DeprecatedTextureClient> textureClient =
|
|
||||||
new DeprecatedTextureClientTile(mManager->AsShadowForwarder(), TextureInfo(BUFFER_TILED));
|
|
||||||
aTile.mDeprecatedTextureClient = static_cast<DeprecatedTextureClientTile*>(textureClient.get());
|
|
||||||
}
|
|
||||||
aTile.mDeprecatedTextureClient->EnsureAllocated(gfx::IntSize(GetTileLength(), GetTileLength()), GetContentType());
|
|
||||||
gfxImageSurface* writableSurface = aTile.mDeprecatedTextureClient->LockImageSurface();
|
|
||||||
// Bug 742100, this gfxContext really should live on the stack.
|
|
||||||
nsRefPtr<gfxContext> ctxt;
|
|
||||||
|
|
||||||
RefPtr<gfx::DrawTarget> writableDrawTarget;
|
|
||||||
if (gfxPlatform::GetPlatform()->SupportsAzureContent()) {
|
|
||||||
// TODO: Instead of creating a gfxImageSurface to back the tile we should
|
|
||||||
// create an offscreen DrawTarget. This would need to be shared cross-thread
|
|
||||||
// and support copy on write semantics.
|
|
||||||
gfx::SurfaceFormat format =
|
|
||||||
gfx::ImageFormatToSurfaceFormat(writableSurface->Format());
|
|
||||||
|
|
||||||
writableDrawTarget =
|
|
||||||
gfxPlatform::GetPlatform()->CreateDrawTargetForData(
|
|
||||||
writableSurface->Data(),
|
|
||||||
gfx::IntSize(writableSurface->Width(), writableSurface->Height()),
|
|
||||||
writableSurface->Stride(),
|
|
||||||
format);
|
|
||||||
ctxt = new gfxContext(writableDrawTarget);
|
|
||||||
} else {
|
|
||||||
ctxt = new gfxContext(writableSurface);
|
|
||||||
ctxt->SetOperator(gfxContext::OPERATOR_SOURCE);
|
|
||||||
}
|
|
||||||
|
|
||||||
gfxRect drawRect(aDirtyRect.x - aTileOrigin.x, aDirtyRect.y - aTileOrigin.y,
|
|
||||||
aDirtyRect.width, aDirtyRect.height);
|
|
||||||
|
|
||||||
if (mSinglePaintBuffer || mSinglePaintDrawTarget) {
|
|
||||||
if (gfxPlatform::GetPlatform()->SupportsAzureContent()) {
|
|
||||||
gfx::Rect drawRect(aDirtyRect.x - aTileOrigin.x,
|
|
||||||
aDirtyRect.y - aTileOrigin.y,
|
|
||||||
aDirtyRect.width,
|
|
||||||
aDirtyRect.height);
|
|
||||||
drawRect.Scale(mResolution);
|
|
||||||
|
|
||||||
RefPtr<gfx::SourceSurface> source = mSinglePaintDrawTarget->Snapshot();
|
|
||||||
writableDrawTarget->CopySurface(
|
|
||||||
source,
|
|
||||||
gfx::IntRect(NS_roundf((aDirtyRect.x - mSinglePaintBufferOffset.x) * mResolution),
|
|
||||||
NS_roundf((aDirtyRect.y - mSinglePaintBufferOffset.y) * mResolution),
|
|
||||||
drawRect.width,
|
|
||||||
drawRect.height),
|
|
||||||
gfx::IntPoint(NS_roundf(drawRect.x), NS_roundf(drawRect.y)));
|
|
||||||
} else {
|
|
||||||
gfxRect drawRect(aDirtyRect.x - aTileOrigin.x, aDirtyRect.y - aTileOrigin.y,
|
|
||||||
aDirtyRect.width, aDirtyRect.height);
|
|
||||||
drawRect.Scale(mResolution, mResolution);
|
|
||||||
|
|
||||||
ctxt->NewPath();
|
|
||||||
ctxt->SetSource(mSinglePaintBuffer.get(),
|
|
||||||
gfxPoint((mSinglePaintBufferOffset.x - aDirtyRect.x) * mResolution + drawRect.x,
|
|
||||||
(mSinglePaintBufferOffset.y - aDirtyRect.y) * mResolution + drawRect.y));
|
|
||||||
ctxt->SnappedRectangle(drawRect);
|
|
||||||
ctxt->Fill();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ctxt->NewPath();
|
|
||||||
ctxt->Scale(mResolution, mResolution);
|
|
||||||
ctxt->Translate(gfxPoint(-aTileOrigin.x, -aTileOrigin.y));
|
|
||||||
nsIntPoint a = nsIntPoint(aTileOrigin.x, aTileOrigin.y);
|
|
||||||
mCallback(mThebesLayer, ctxt,
|
|
||||||
nsIntRegion(nsIntRect(a, nsIntSize(GetScaledTileLength(),
|
|
||||||
GetScaledTileLength()))),
|
|
||||||
DrawRegionClip::CLIP_NONE,
|
|
||||||
nsIntRegion(), mCallbackData);
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef GFX_TILEDLAYER_DEBUG_OVERLAY
|
|
||||||
DrawDebugOverlay(writableSurface, aTileOrigin.x * mResolution,
|
|
||||||
aTileOrigin.y * mResolution);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return aTile;
|
|
||||||
}
|
|
||||||
|
|
||||||
BasicTiledLayerTile
|
|
||||||
BasicTiledLayerBuffer::ValidateTile(BasicTiledLayerTile aTile,
|
|
||||||
const nsIntPoint& aTileOrigin,
|
const nsIntPoint& aTileOrigin,
|
||||||
const nsIntRegion& aDirtyRegion)
|
const nsIntRegion& aDirtyRegion)
|
||||||
{
|
{
|
||||||
PROFILER_LABEL("BasicTiledLayerBuffer", "ValidateTile");
|
PROFILER_LABEL("ClientTiledLayerBuffer", "ValidateTile");
|
||||||
|
|
||||||
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
|
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
|
||||||
if (aDirtyRegion.IsComplex()) {
|
if (aDirtyRegion.IsComplex()) {
|
||||||
|
@ -540,12 +703,140 @@ BasicTiledLayerBuffer::ValidateTile(BasicTiledLayerTile aTile,
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (aTile.IsPlaceholderTile()) {
|
||||||
|
aTile.SetLayerManager(mManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Discard our front and backbuffers if our contents changed. In this case
|
||||||
|
// the calling code will already have taken care of invalidating the entire
|
||||||
|
// layer.
|
||||||
|
if (HasFormatChanged()) {
|
||||||
|
aTile.DiscardBackBuffer();
|
||||||
|
aTile.DiscardFrontBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool createdTextureClient = false;
|
||||||
|
nsIntRegion offsetDirtyRegion = aDirtyRegion.MovedBy(-aTileOrigin);
|
||||||
|
bool usingSinglePaintBuffer = !!mSinglePaintDrawTarget;
|
||||||
|
RefPtr<TextureClient> backBuffer =
|
||||||
|
aTile.GetBackBuffer(offsetDirtyRegion,
|
||||||
|
mManager->GetTexturePool(gfxPlatform::GetPlatform()->Optimal2DFormatForContent(GetContentType())),
|
||||||
|
&createdTextureClient, !usingSinglePaintBuffer);
|
||||||
|
|
||||||
|
if (!backBuffer->Lock(OPEN_READ_WRITE)) {
|
||||||
|
NS_WARNING("Failed to lock tile TextureClient for updating.");
|
||||||
|
aTile.DiscardFrontBuffer();
|
||||||
|
return aTile;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We must not keep a reference to the DrawTarget after it has been unlocked,
|
||||||
|
// make sure these are null'd before unlocking as destruction of the context
|
||||||
|
// may cause the target to be flushed.
|
||||||
|
RefPtr<DrawTarget> drawTarget = backBuffer->AsTextureClientDrawTarget()->GetAsDrawTarget();
|
||||||
|
drawTarget->SetTransform(Matrix());
|
||||||
|
|
||||||
|
RefPtr<gfxContext> ctxt = new gfxContext(drawTarget);
|
||||||
|
|
||||||
|
if (usingSinglePaintBuffer) {
|
||||||
|
// XXX Perhaps we should just copy the bounding rectangle here?
|
||||||
|
RefPtr<gfx::SourceSurface> source = mSinglePaintDrawTarget->Snapshot();
|
||||||
nsIntRegionRectIterator it(aDirtyRegion);
|
nsIntRegionRectIterator it(aDirtyRegion);
|
||||||
for (const nsIntRect* rect = it.Next(); rect != nullptr; rect = it.Next()) {
|
for (const nsIntRect* dirtyRect = it.Next(); dirtyRect != nullptr; dirtyRect = it.Next()) {
|
||||||
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
|
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
|
||||||
printf_stderr(" break into subrect %i, %i, %i, %i\n", rect->x, rect->y, rect->width, rect->height);
|
printf_stderr(" break into subdirtyRect %i, %i, %i, %i\n",
|
||||||
|
dirtyRect->x, dirtyRect->y, dirtyRect->width, dirtyRect->height);
|
||||||
#endif
|
#endif
|
||||||
aTile = ValidateTileInternal(aTile, aTileOrigin, *rect);
|
gfx::Rect drawRect(dirtyRect->x - aTileOrigin.x,
|
||||||
|
dirtyRect->y - aTileOrigin.y,
|
||||||
|
dirtyRect->width,
|
||||||
|
dirtyRect->height);
|
||||||
|
drawRect.Scale(mResolution);
|
||||||
|
|
||||||
|
gfx::IntRect copyRect(NS_roundf((dirtyRect->x - mSinglePaintBufferOffset.x) * mResolution),
|
||||||
|
NS_roundf((dirtyRect->y - mSinglePaintBufferOffset.y) * mResolution),
|
||||||
|
drawRect.width,
|
||||||
|
drawRect.height);
|
||||||
|
gfx::IntPoint copyTarget(NS_roundf(drawRect.x), NS_roundf(drawRect.y));
|
||||||
|
drawTarget->CopySurface(source, copyRect, copyTarget);
|
||||||
|
|
||||||
|
// Mark the newly updated area as invalid in the front buffer
|
||||||
|
aTile.mInvalidFront.Or(aTile.mInvalidFront, nsIntRect(copyTarget.x, copyTarget.y, copyRect.width, copyRect.height));
|
||||||
|
}
|
||||||
|
|
||||||
|
// The new buffer is now validated, remove the dirty region from it.
|
||||||
|
aTile.mInvalidBack.Sub(nsIntRect(0, 0, TILEDLAYERBUFFER_TILE_SIZE, TILEDLAYERBUFFER_TILE_SIZE),
|
||||||
|
offsetDirtyRegion);
|
||||||
|
} else {
|
||||||
|
// Area of the full tile...
|
||||||
|
nsIntRegion tileRegion = nsIntRect(aTileOrigin.x, aTileOrigin.y, TILEDLAYERBUFFER_TILE_SIZE, TILEDLAYERBUFFER_TILE_SIZE);
|
||||||
|
|
||||||
|
// Intersect this area with the portion that's dirty.
|
||||||
|
tileRegion = tileRegion.Intersect(aDirtyRegion);
|
||||||
|
|
||||||
|
// Move invalid areas into layer space.
|
||||||
|
aTile.mInvalidFront.MoveBy(aTileOrigin);
|
||||||
|
aTile.mInvalidBack.MoveBy(aTileOrigin);
|
||||||
|
|
||||||
|
// Add the area that's going to be redrawn to the invalid area of the
|
||||||
|
// front region.
|
||||||
|
aTile.mInvalidFront.Or(aTile.mInvalidFront, tileRegion);
|
||||||
|
|
||||||
|
// Add invalid areas of the backbuffer to the area to redraw.
|
||||||
|
tileRegion.Or(tileRegion, aTile.mInvalidBack);
|
||||||
|
|
||||||
|
// Move invalid areas back into tile space.
|
||||||
|
aTile.mInvalidFront.MoveBy(-aTileOrigin);
|
||||||
|
|
||||||
|
// This will be validated now.
|
||||||
|
aTile.mInvalidBack.SetEmpty();
|
||||||
|
|
||||||
|
nsIntRect bounds = tileRegion.GetBounds();
|
||||||
|
bounds.ScaleRoundOut(mResolution, mResolution);
|
||||||
|
bounds.MoveBy(-aTileOrigin);
|
||||||
|
|
||||||
|
if (GetContentType() != gfxContentType::COLOR) {
|
||||||
|
drawTarget->ClearRect(Rect(bounds.x, bounds.y, bounds.width, bounds.height));
|
||||||
|
}
|
||||||
|
|
||||||
|
ctxt->NewPath();
|
||||||
|
ctxt->Clip(gfxRect(bounds.x, bounds.y, bounds.width, bounds.height));
|
||||||
|
ctxt->Scale(mResolution, mResolution);
|
||||||
|
ctxt->Translate(gfxPoint(-aTileOrigin.x, -aTileOrigin.y));
|
||||||
|
mCallback(mThebesLayer, ctxt,
|
||||||
|
tileRegion.GetBounds(),
|
||||||
|
DrawRegionClip::CLIP_NONE,
|
||||||
|
nsIntRegion(), mCallbackData);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef GFX_TILEDLAYER_DEBUG_OVERLAY
|
||||||
|
DrawDebugOverlay(drawTarget, aTileOrigin.x * mResolution,
|
||||||
|
aTileOrigin.y * mResolution, GetTileLength(), GetTileLength());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ctxt = nullptr;
|
||||||
|
drawTarget = nullptr;
|
||||||
|
|
||||||
|
backBuffer->Unlock();
|
||||||
|
|
||||||
|
aTile.Flip();
|
||||||
|
|
||||||
|
if (createdTextureClient) {
|
||||||
|
if (!mCompositableClient->AddTextureClient(backBuffer)) {
|
||||||
|
NS_WARNING("Failed to add tile TextureClient.");
|
||||||
|
aTile.DiscardFrontBuffer();
|
||||||
|
aTile.DiscardBackBuffer();
|
||||||
|
return aTile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note, we don't call UpdatedTexture. The Updated function is called manually
|
||||||
|
// by the TiledContentHost before composition.
|
||||||
|
|
||||||
|
if (backBuffer->HasInternalBuffer()) {
|
||||||
|
// If our new buffer has an internal buffer, we don't want to keep another
|
||||||
|
// TextureClient around unnecessarily, so discard the back-buffer.
|
||||||
|
aTile.DiscardBackBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
return aTile;
|
return aTile;
|
||||||
|
@ -576,7 +867,7 @@ TransformCompositionBounds(const ScreenRect& aCompositionBounds,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
BasicTiledLayerBuffer::ComputeProgressiveUpdateRegion(const nsIntRegion& aInvalidRegion,
|
ClientTiledLayerBuffer::ComputeProgressiveUpdateRegion(const nsIntRegion& aInvalidRegion,
|
||||||
const nsIntRegion& aOldValidRegion,
|
const nsIntRegion& aOldValidRegion,
|
||||||
nsIntRegion& aRegionToPaint,
|
nsIntRegion& aRegionToPaint,
|
||||||
BasicTiledLayerPaintData* aPaintData,
|
BasicTiledLayerPaintData* aPaintData,
|
||||||
|
@ -735,7 +1026,7 @@ BasicTiledLayerBuffer::ComputeProgressiveUpdateRegion(const nsIntRegion& aInvali
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
BasicTiledLayerBuffer::ProgressiveUpdate(nsIntRegion& aValidRegion,
|
ClientTiledLayerBuffer::ProgressiveUpdate(nsIntRegion& aValidRegion,
|
||||||
nsIntRegion& aInvalidRegion,
|
nsIntRegion& aInvalidRegion,
|
||||||
const nsIntRegion& aOldValidRegion,
|
const nsIntRegion& aOldValidRegion,
|
||||||
BasicTiledLayerPaintData* aPaintData,
|
BasicTiledLayerPaintData* aPaintData,
|
||||||
|
|
|
@ -16,9 +16,14 @@
|
||||||
#include "gfxTypes.h"
|
#include "gfxTypes.h"
|
||||||
#include "mozilla/Attributes.h" // for MOZ_OVERRIDE
|
#include "mozilla/Attributes.h" // for MOZ_OVERRIDE
|
||||||
#include "mozilla/RefPtr.h" // for RefPtr
|
#include "mozilla/RefPtr.h" // for RefPtr
|
||||||
|
#include "mozilla/ipc/Shmem.h" // for Shmem
|
||||||
|
#include "mozilla/ipc/SharedMemory.h" // for SharedMemory
|
||||||
#include "mozilla/layers/CompositableClient.h" // for CompositableClient
|
#include "mozilla/layers/CompositableClient.h" // for CompositableClient
|
||||||
#include "mozilla/layers/CompositorTypes.h" // for TextureInfo, etc
|
#include "mozilla/layers/CompositorTypes.h" // for TextureInfo, etc
|
||||||
|
#include "mozilla/layers/LayersMessages.h" // for TileDescriptor
|
||||||
#include "mozilla/layers/TextureClient.h"
|
#include "mozilla/layers/TextureClient.h"
|
||||||
|
#include "mozilla/layers/TextureClientPool.h"
|
||||||
|
#include "ClientLayerManager.h"
|
||||||
#include "mozilla/mozalloc.h" // for operator delete
|
#include "mozilla/mozalloc.h" // for operator delete
|
||||||
#include "nsAutoPtr.h" // for nsRefPtr
|
#include "nsAutoPtr.h" // for nsRefPtr
|
||||||
#include "nsISupportsImpl.h" // for MOZ_COUNT_DTOR
|
#include "nsISupportsImpl.h" // for MOZ_COUNT_DTOR
|
||||||
|
@ -28,6 +33,8 @@
|
||||||
#include "nsTArray.h" // for nsTArray, nsTArray_Impl, etc
|
#include "nsTArray.h" // for nsTArray, nsTArray_Impl, etc
|
||||||
#include "mozilla/layers/ISurfaceAllocator.h"
|
#include "mozilla/layers/ISurfaceAllocator.h"
|
||||||
#include "gfxReusableSurfaceWrapper.h"
|
#include "gfxReusableSurfaceWrapper.h"
|
||||||
|
#include "pratom.h" // For PR_ATOMIC_INCREMENT/DECREMENT
|
||||||
|
#include "gfxPrefs.h"
|
||||||
|
|
||||||
class gfxImageSurface;
|
class gfxImageSurface;
|
||||||
|
|
||||||
|
@ -35,67 +42,186 @@ namespace mozilla {
|
||||||
namespace layers {
|
namespace layers {
|
||||||
|
|
||||||
class BasicTileDescriptor;
|
class BasicTileDescriptor;
|
||||||
|
class ClientTiledThebesLayer;
|
||||||
|
class ClientLayerManager;
|
||||||
|
|
||||||
|
|
||||||
|
// A class to help implement copy-on-write semantics for shared tiles.
|
||||||
|
class gfxSharedReadLock : public AtomicRefCounted<gfxSharedReadLock> {
|
||||||
|
public:
|
||||||
|
MOZ_DECLARE_REFCOUNTED_TYPENAME(gfxSharedReadLock)
|
||||||
|
virtual ~gfxSharedReadLock() {}
|
||||||
|
|
||||||
|
virtual int32_t ReadLock() = 0;
|
||||||
|
virtual int32_t ReadUnlock() = 0;
|
||||||
|
virtual int32_t GetReadCount() = 0;
|
||||||
|
|
||||||
|
enum gfxSharedReadLockType {
|
||||||
|
TYPE_MEMORY,
|
||||||
|
TYPE_SHMEM
|
||||||
|
};
|
||||||
|
virtual gfxSharedReadLockType GetType() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
NS_DECL_OWNINGTHREAD
|
||||||
|
};
|
||||||
|
|
||||||
|
class gfxMemorySharedReadLock : public gfxSharedReadLock {
|
||||||
|
public:
|
||||||
|
gfxMemorySharedReadLock();
|
||||||
|
|
||||||
|
~gfxMemorySharedReadLock();
|
||||||
|
|
||||||
|
virtual int32_t ReadLock() MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
virtual int32_t ReadUnlock() MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
virtual int32_t GetReadCount() MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
virtual gfxSharedReadLockType GetType() MOZ_OVERRIDE { return TYPE_MEMORY; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
int32_t mReadCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
class gfxShmSharedReadLock : public gfxSharedReadLock {
|
||||||
|
private:
|
||||||
|
struct ShmReadLockInfo {
|
||||||
|
int32_t readCount;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
gfxShmSharedReadLock(ISurfaceAllocator* aAllocator);
|
||||||
|
|
||||||
|
~gfxShmSharedReadLock();
|
||||||
|
|
||||||
|
virtual int32_t ReadLock() MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
virtual int32_t ReadUnlock() MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
virtual int32_t GetReadCount() MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
virtual gfxSharedReadLockType GetType() MOZ_OVERRIDE { return TYPE_SHMEM; }
|
||||||
|
|
||||||
|
mozilla::ipc::Shmem& GetShmem() { return mShmem; }
|
||||||
|
|
||||||
|
static already_AddRefed<gfxShmSharedReadLock>
|
||||||
|
Open(mozilla::layers::ISurfaceAllocator* aAllocator, const mozilla::ipc::Shmem& aShmem)
|
||||||
|
{
|
||||||
|
nsRefPtr<gfxShmSharedReadLock> readLock = new gfxShmSharedReadLock(aAllocator, aShmem);
|
||||||
|
return readLock.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
gfxShmSharedReadLock(ISurfaceAllocator* aAllocator, const mozilla::ipc::Shmem& aShmem)
|
||||||
|
: mAllocator(aAllocator)
|
||||||
|
, mShmem(aShmem)
|
||||||
|
{
|
||||||
|
MOZ_COUNT_CTOR(gfxShmSharedReadLock);
|
||||||
|
}
|
||||||
|
|
||||||
|
ShmReadLockInfo* GetShmReadLockInfoPtr()
|
||||||
|
{
|
||||||
|
return reinterpret_cast<ShmReadLockInfo*>
|
||||||
|
(mShmem.get<char>() + mShmem.Size<char>() - sizeof(ShmReadLockInfo));
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<ISurfaceAllocator> mAllocator;
|
||||||
|
mozilla::ipc::Shmem mShmem;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represent a single tile in tiled buffer. The buffer keeps tiles,
|
* Represent a single tile in tiled buffer. The buffer keeps tiles,
|
||||||
* each tile keeps a reference to a texture client. The texture client
|
* each tile keeps a reference to a texture client and a read-lock. This
|
||||||
* is backed by a gfxReusableSurfaceWrapper that implements a
|
* read-lock is used to help implement a copy-on-write mechanism. The tile
|
||||||
* copy-on-write mechanism while locked. The tile should be
|
* should be locked before being sent to the compositor. The compositor should
|
||||||
* locked before being sent to the compositor and unlocked
|
* unlock the read-lock as soon as it has finished with the buffer in the
|
||||||
* as soon as it is uploaded to prevent a copy.
|
* TextureHost to prevent more textures being created than is necessary.
|
||||||
* Ideal place to store per tile debug information.
|
* Ideal place to store per tile debug information.
|
||||||
*/
|
*/
|
||||||
struct BasicTiledLayerTile {
|
struct TileClient
|
||||||
RefPtr<DeprecatedTextureClientTile> mDeprecatedTextureClient;
|
{
|
||||||
#ifdef GFX_TILEDLAYER_DEBUG_OVERLAY
|
|
||||||
TimeStamp mLastUpdate;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Placeholder
|
// Placeholder
|
||||||
BasicTiledLayerTile()
|
TileClient();
|
||||||
: mDeprecatedTextureClient(nullptr)
|
|
||||||
{}
|
|
||||||
|
|
||||||
BasicTiledLayerTile(DeprecatedTextureClientTile* aTextureClient)
|
TileClient(const TileClient& o);
|
||||||
: mDeprecatedTextureClient(aTextureClient)
|
|
||||||
{}
|
|
||||||
|
|
||||||
BasicTiledLayerTile(const BasicTiledLayerTile& o) {
|
TileClient& operator=(const TileClient& o);
|
||||||
mDeprecatedTextureClient = o.mDeprecatedTextureClient;
|
|
||||||
#ifdef GFX_TILEDLAYER_DEBUG_OVERLAY
|
bool operator== (const TileClient& o) const
|
||||||
mLastUpdate = o.mLastUpdate;
|
{
|
||||||
#endif
|
return mFrontBuffer == o.mFrontBuffer;
|
||||||
}
|
|
||||||
BasicTiledLayerTile& operator=(const BasicTiledLayerTile& o) {
|
|
||||||
if (this == &o) return *this;
|
|
||||||
mDeprecatedTextureClient = o.mDeprecatedTextureClient;
|
|
||||||
#ifdef GFX_TILEDLAYER_DEBUG_OVERLAY
|
|
||||||
mLastUpdate = o.mLastUpdate;
|
|
||||||
#endif
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
bool operator== (const BasicTiledLayerTile& o) const {
|
|
||||||
return mDeprecatedTextureClient == o.mDeprecatedTextureClient;
|
|
||||||
}
|
|
||||||
bool operator!= (const BasicTiledLayerTile& o) const {
|
|
||||||
return mDeprecatedTextureClient != o.mDeprecatedTextureClient;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsPlaceholderTile() { return mDeprecatedTextureClient == nullptr; }
|
bool operator!= (const TileClient& o) const
|
||||||
|
{
|
||||||
void ReadUnlock() {
|
return mFrontBuffer != o.mFrontBuffer;
|
||||||
GetSurface()->ReadUnlock();
|
|
||||||
}
|
}
|
||||||
void ReadLock() {
|
|
||||||
GetSurface()->ReadLock();
|
void SetLayerManager(ClientLayerManager *aManager)
|
||||||
|
{
|
||||||
|
mManager = aManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsPlaceholderTile()
|
||||||
|
{
|
||||||
|
return mBackBuffer == nullptr && mFrontBuffer == nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReadUnlock()
|
||||||
|
{
|
||||||
|
NS_ASSERTION(mFrontLock != nullptr, "ReadUnlock with no gfxSharedReadLock");
|
||||||
|
mFrontLock->ReadUnlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReadLock()
|
||||||
|
{
|
||||||
|
NS_ASSERTION(mFrontLock != nullptr, "ReadLock with no gfxSharedReadLock");
|
||||||
|
mFrontLock->ReadLock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Release()
|
||||||
|
{
|
||||||
|
DiscardFrontBuffer();
|
||||||
|
DiscardBackBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
TileDescriptor GetTileDescriptor();
|
TileDescriptor GetTileDescriptor();
|
||||||
static BasicTiledLayerTile OpenDescriptor(ISurfaceAllocator *aAllocator, const TileDescriptor& aDesc);
|
|
||||||
|
|
||||||
gfxReusableSurfaceWrapper* GetSurface() {
|
/**
|
||||||
return mDeprecatedTextureClient->GetReusableSurfaceWrapper();
|
* Swaps the front and back buffers.
|
||||||
}
|
*/
|
||||||
|
void Flip();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an unlocked TextureClient that can be used for writing new
|
||||||
|
* data to the tile. This may flip the front-buffer to the back-buffer if
|
||||||
|
* the front-buffer is still locked by the host, or does not have an
|
||||||
|
* internal buffer (and so will always be locked).
|
||||||
|
*/
|
||||||
|
TextureClient* GetBackBuffer(const nsIntRegion& aDirtyRegion,
|
||||||
|
TextureClientPool *aPool,
|
||||||
|
bool *aCreatedTextureClient,
|
||||||
|
bool aCanRerasterizeValidRegion);
|
||||||
|
|
||||||
|
void DiscardFrontBuffer();
|
||||||
|
|
||||||
|
void DiscardBackBuffer();
|
||||||
|
|
||||||
|
RefPtr<TextureClient> mBackBuffer;
|
||||||
|
RefPtr<TextureClient> mFrontBuffer;
|
||||||
|
RefPtr<gfxSharedReadLock> mBackLock;
|
||||||
|
RefPtr<gfxSharedReadLock> mFrontLock;
|
||||||
|
RefPtr<ClientLayerManager> mManager;
|
||||||
|
#ifdef GFX_TILEDLAYER_DEBUG_OVERLAY
|
||||||
|
TimeStamp mLastUpdate;
|
||||||
|
#endif
|
||||||
|
nsIntRegion mInvalidFront;
|
||||||
|
nsIntRegion mInvalidBack;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void ValidateBackBufferFromFront(const nsIntRegion &aDirtyRegion,
|
||||||
|
bool aCanRerasterizeValidRegion);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -165,9 +291,6 @@ struct BasicTiledLayerPaintData {
|
||||||
bool mPaintFinished : 1;
|
bool mPaintFinished : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ClientTiledThebesLayer;
|
|
||||||
class ClientLayerManager;
|
|
||||||
|
|
||||||
class SharedFrameMetricsHelper
|
class SharedFrameMetricsHelper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -210,72 +333,45 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provide an instance of TiledLayerBuffer backed by image surfaces.
|
* Provide an instance of TiledLayerBuffer backed by drawable TextureClients.
|
||||||
* This buffer provides an implementation to ValidateTile using a
|
* This buffer provides an implementation of ValidateTile using a
|
||||||
* thebes callback and can support painting using a single paint buffer
|
* thebes callback and can support painting using a single paint buffer.
|
||||||
* which is much faster then painting directly into the tiles.
|
* Whether a single paint buffer is used is controlled by
|
||||||
|
* gfxPrefs::PerTileDrawing().
|
||||||
*/
|
*/
|
||||||
class BasicTiledLayerBuffer
|
class ClientTiledLayerBuffer
|
||||||
: public TiledLayerBuffer<BasicTiledLayerBuffer, BasicTiledLayerTile>
|
: public TiledLayerBuffer<ClientTiledLayerBuffer, TileClient>
|
||||||
{
|
{
|
||||||
friend class TiledLayerBuffer<BasicTiledLayerBuffer, BasicTiledLayerTile>;
|
friend class TiledLayerBuffer<ClientTiledLayerBuffer, TileClient>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BasicTiledLayerBuffer(ClientTiledThebesLayer* aThebesLayer,
|
ClientTiledLayerBuffer(ClientTiledThebesLayer* aThebesLayer,
|
||||||
|
CompositableClient* aCompositableClient,
|
||||||
ClientLayerManager* aManager,
|
ClientLayerManager* aManager,
|
||||||
SharedFrameMetricsHelper* aHelper);
|
SharedFrameMetricsHelper* aHelper);
|
||||||
BasicTiledLayerBuffer()
|
ClientTiledLayerBuffer()
|
||||||
: mThebesLayer(nullptr)
|
: mThebesLayer(nullptr)
|
||||||
|
, mCompositableClient(nullptr)
|
||||||
, mManager(nullptr)
|
, mManager(nullptr)
|
||||||
, mLastPaintOpaque(false)
|
, mLastPaintOpaque(false)
|
||||||
, mSharedFrameMetricsHelper(nullptr)
|
, mSharedFrameMetricsHelper(nullptr)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
BasicTiledLayerBuffer(ISurfaceAllocator* aAllocator,
|
|
||||||
const nsIntRegion& aValidRegion,
|
|
||||||
const nsIntRegion& aPaintedRegion,
|
|
||||||
const InfallibleTArray<TileDescriptor>& aTiles,
|
|
||||||
int aRetainedWidth,
|
|
||||||
int aRetainedHeight,
|
|
||||||
float aResolution,
|
|
||||||
SharedFrameMetricsHelper* aHelper)
|
|
||||||
{
|
|
||||||
mSharedFrameMetricsHelper = aHelper;
|
|
||||||
mValidRegion = aValidRegion;
|
|
||||||
mPaintedRegion = aPaintedRegion;
|
|
||||||
mRetainedWidth = aRetainedWidth;
|
|
||||||
mRetainedHeight = aRetainedHeight;
|
|
||||||
mResolution = aResolution;
|
|
||||||
|
|
||||||
for(size_t i = 0; i < aTiles.Length(); i++) {
|
|
||||||
if (aTiles[i].type() == TileDescriptor::TPlaceholderTileDescriptor) {
|
|
||||||
mRetainedTiles.AppendElement(GetPlaceholderTile());
|
|
||||||
} else {
|
|
||||||
mRetainedTiles.AppendElement(BasicTiledLayerTile::OpenDescriptor(aAllocator, aTiles[i]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PaintThebes(const nsIntRegion& aNewValidRegion,
|
void PaintThebes(const nsIntRegion& aNewValidRegion,
|
||||||
const nsIntRegion& aPaintRegion,
|
const nsIntRegion& aPaintRegion,
|
||||||
LayerManager::DrawThebesLayerCallback aCallback,
|
LayerManager::DrawThebesLayerCallback aCallback,
|
||||||
void* aCallbackData);
|
void* aCallbackData);
|
||||||
|
|
||||||
void ReadUnlock() {
|
void ReadUnlock();
|
||||||
for (size_t i = 0; i < mRetainedTiles.Length(); i++) {
|
|
||||||
if (mRetainedTiles[i].IsPlaceholderTile()) continue;
|
|
||||||
mRetainedTiles[i].ReadUnlock();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ReadLock() {
|
void ReadLock();
|
||||||
for (size_t i = 0; i < mRetainedTiles.Length(); i++) {
|
|
||||||
if (mRetainedTiles[i].IsPlaceholderTile()) continue;
|
void Release();
|
||||||
mRetainedTiles[i].ReadLock();
|
|
||||||
}
|
void DiscardBackBuffers();
|
||||||
}
|
|
||||||
|
|
||||||
const CSSToScreenScale& GetFrameResolution() { return mFrameResolution; }
|
const CSSToScreenScale& GetFrameResolution() { return mFrameResolution; }
|
||||||
|
|
||||||
void SetFrameResolution(const CSSToScreenScale& aResolution) { mFrameResolution = aResolution; }
|
void SetFrameResolution(const CSSToScreenScale& aResolution) { mFrameResolution = aResolution; }
|
||||||
|
|
||||||
bool HasFormatChanged() const;
|
bool HasFormatChanged() const;
|
||||||
|
@ -293,12 +389,8 @@ public:
|
||||||
|
|
||||||
SurfaceDescriptorTiles GetSurfaceDescriptorTiles();
|
SurfaceDescriptorTiles GetSurfaceDescriptorTiles();
|
||||||
|
|
||||||
static BasicTiledLayerBuffer OpenDescriptor(ISurfaceAllocator* aAllocator,
|
|
||||||
const SurfaceDescriptorTiles& aDescriptor,
|
|
||||||
SharedFrameMetricsHelper* aHelper);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
BasicTiledLayerTile ValidateTile(BasicTiledLayerTile aTile,
|
TileClient ValidateTile(TileClient aTile,
|
||||||
const nsIntPoint& aTileRect,
|
const nsIntPoint& aTileRect,
|
||||||
const nsIntRegion& dirtyRect);
|
const nsIntRegion& dirtyRect);
|
||||||
|
|
||||||
|
@ -306,35 +398,29 @@ protected:
|
||||||
// buffer and copy it out to the tiles instead of calling PaintThebes() on
|
// buffer and copy it out to the tiles instead of calling PaintThebes() on
|
||||||
// each tile individually. Somewhat surprisingly, this turns out to be faster
|
// each tile individually. Somewhat surprisingly, this turns out to be faster
|
||||||
// on Android.
|
// on Android.
|
||||||
bool UseSinglePaintBuffer() { return true; }
|
bool UseSinglePaintBuffer() { return !gfxPrefs::PerTileDrawing(); }
|
||||||
|
|
||||||
void ReleaseTile(BasicTiledLayerTile aTile) { /* No-op. */ }
|
void ReleaseTile(TileClient aTile) { aTile.Release(); }
|
||||||
|
|
||||||
void SwapTiles(BasicTiledLayerTile& aTileA, BasicTiledLayerTile& aTileB) {
|
void SwapTiles(TileClient& aTileA, TileClient& aTileB) { std::swap(aTileA, aTileB); }
|
||||||
std::swap(aTileA, aTileB);
|
|
||||||
}
|
|
||||||
|
|
||||||
BasicTiledLayerTile GetPlaceholderTile() const { return BasicTiledLayerTile(); }
|
TileClient GetPlaceholderTile() const { return TileClient(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
gfxContentType GetContentType() const;
|
gfxContentType GetContentType() const;
|
||||||
ClientTiledThebesLayer* mThebesLayer;
|
ClientTiledThebesLayer* mThebesLayer;
|
||||||
|
CompositableClient* mCompositableClient;
|
||||||
ClientLayerManager* mManager;
|
ClientLayerManager* mManager;
|
||||||
LayerManager::DrawThebesLayerCallback mCallback;
|
LayerManager::DrawThebesLayerCallback mCallback;
|
||||||
void* mCallbackData;
|
void* mCallbackData;
|
||||||
CSSToScreenScale mFrameResolution;
|
CSSToScreenScale mFrameResolution;
|
||||||
bool mLastPaintOpaque;
|
bool mLastPaintOpaque;
|
||||||
|
|
||||||
// The buffer we use when UseSinglePaintBuffer() above is true.
|
// The DrawTarget we use when UseSinglePaintBuffer() above is true.
|
||||||
nsRefPtr<gfxImageSurface> mSinglePaintBuffer;
|
|
||||||
RefPtr<gfx::DrawTarget> mSinglePaintDrawTarget;
|
RefPtr<gfx::DrawTarget> mSinglePaintDrawTarget;
|
||||||
nsIntPoint mSinglePaintBufferOffset;
|
nsIntPoint mSinglePaintBufferOffset;
|
||||||
SharedFrameMetricsHelper* mSharedFrameMetricsHelper;
|
SharedFrameMetricsHelper* mSharedFrameMetricsHelper;
|
||||||
|
|
||||||
BasicTiledLayerTile ValidateTileInternal(BasicTiledLayerTile aTile,
|
|
||||||
const nsIntPoint& aTileOrigin,
|
|
||||||
const nsIntRect& aDirtyRect);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculates the region to update in a single progressive update transaction.
|
* Calculates the region to update in a single progressive update transaction.
|
||||||
* This employs some heuristics to update the most 'sensible' region to
|
* This employs some heuristics to update the most 'sensible' region to
|
||||||
|
@ -374,6 +460,9 @@ public:
|
||||||
~TiledContentClient()
|
~TiledContentClient()
|
||||||
{
|
{
|
||||||
MOZ_COUNT_DTOR(TiledContentClient);
|
MOZ_COUNT_DTOR(TiledContentClient);
|
||||||
|
|
||||||
|
mTiledBuffer.Release();
|
||||||
|
mLowPrecisionTiledBuffer.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE
|
virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE
|
||||||
|
@ -381,16 +470,18 @@ public:
|
||||||
return TextureInfo(BUFFER_TILED);
|
return TextureInfo(BUFFER_TILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual void ClearCachedResources() MOZ_OVERRIDE;
|
||||||
|
|
||||||
enum TiledBufferType {
|
enum TiledBufferType {
|
||||||
TILED_BUFFER,
|
TILED_BUFFER,
|
||||||
LOW_PRECISION_TILED_BUFFER
|
LOW_PRECISION_TILED_BUFFER
|
||||||
};
|
};
|
||||||
void LockCopyAndWrite(TiledBufferType aType);
|
void UseTiledLayerBuffer(TiledBufferType aType);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SharedFrameMetricsHelper mSharedFrameMetricsHelper;
|
SharedFrameMetricsHelper mSharedFrameMetricsHelper;
|
||||||
BasicTiledLayerBuffer mTiledBuffer;
|
ClientTiledLayerBuffer mTiledBuffer;
|
||||||
BasicTiledLayerBuffer mLowPrecisionTiledBuffer;
|
ClientTiledLayerBuffer mLowPrecisionTiledBuffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -174,7 +174,9 @@ CompositableHost::Create(const TextureInfo& aTextureInfo)
|
||||||
default:
|
default:
|
||||||
MOZ_CRASH("Unknown CompositableType");
|
MOZ_CRASH("Unknown CompositableType");
|
||||||
}
|
}
|
||||||
if (result) {
|
// We know that Tiled buffers don't use the compositable backend-specific
|
||||||
|
// data, so don't bother creating it.
|
||||||
|
if (result && aTextureInfo.mCompositableType != BUFFER_TILED) {
|
||||||
RefPtr<CompositableBackendSpecificData> data = CreateCompositableBackendSpecificDataOGL();
|
RefPtr<CompositableBackendSpecificData> data = CreateCompositableBackendSpecificDataOGL();
|
||||||
result->SetCompositableBackendSpecificData(data);
|
result->SetCompositableBackendSpecificData(data);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "nsDebug.h" // for NS_RUNTIMEABORT
|
#include "nsDebug.h" // for NS_RUNTIMEABORT
|
||||||
#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc
|
#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc
|
||||||
#include "nsRegion.h" // for nsIntRegion
|
#include "nsRegion.h" // for nsIntRegion
|
||||||
|
#include "nsTraceRefcnt.h" // for MOZ_COUNT_CTOR, etc
|
||||||
#include "nscore.h" // for nsACString
|
#include "nscore.h" // for nsACString
|
||||||
#include "mozilla/layers/AtomicRefCountedWithFinalize.h"
|
#include "mozilla/layers/AtomicRefCountedWithFinalize.h"
|
||||||
|
|
||||||
|
@ -274,6 +275,7 @@ class TextureHost
|
||||||
void Finalize();
|
void Finalize();
|
||||||
|
|
||||||
friend class AtomicRefCountedWithFinalize<TextureHost>;
|
friend class AtomicRefCountedWithFinalize<TextureHost>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TextureHost(TextureFlags aFlags);
|
TextureHost(TextureFlags aFlags);
|
||||||
|
|
||||||
|
@ -426,6 +428,13 @@ public:
|
||||||
virtual const char *Name() { return "TextureHost"; }
|
virtual const char *Name() { return "TextureHost"; }
|
||||||
virtual void PrintInfo(nsACString& aTo, const char* aPrefix);
|
virtual void PrintInfo(nsACString& aTo, const char* aPrefix);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether the TextureHost implementation is backed by an
|
||||||
|
* in-memory buffer. The consequence of this is that locking the
|
||||||
|
* TextureHost does not contend with locking the texture on the client side.
|
||||||
|
*/
|
||||||
|
virtual bool HasInternalBuffer() const { return false; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cast to a TextureHost for each backend.
|
* Cast to a TextureHost for each backend.
|
||||||
*/
|
*/
|
||||||
|
@ -461,6 +470,7 @@ public:
|
||||||
~BufferTextureHost();
|
~BufferTextureHost();
|
||||||
|
|
||||||
virtual uint8_t* GetBuffer() = 0;
|
virtual uint8_t* GetBuffer() = 0;
|
||||||
|
|
||||||
virtual size_t GetBufferSize() = 0;
|
virtual size_t GetBufferSize() = 0;
|
||||||
|
|
||||||
virtual void Updated(const nsIntRegion* aRegion = nullptr) MOZ_OVERRIDE;
|
virtual void Updated(const nsIntRegion* aRegion = nullptr) MOZ_OVERRIDE;
|
||||||
|
@ -488,6 +498,8 @@ public:
|
||||||
|
|
||||||
virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() MOZ_OVERRIDE;
|
virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return true; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool Upload(nsIntRegion *aRegion = nullptr);
|
bool Upload(nsIntRegion *aRegion = nullptr);
|
||||||
bool MaybeUpload(nsIntRegion *aRegion = nullptr);
|
bool MaybeUpload(nsIntRegion *aRegion = nullptr);
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "nsPrintfCString.h" // for nsPrintfCString
|
#include "nsPrintfCString.h" // for nsPrintfCString
|
||||||
#include "nsRect.h" // for nsIntRect
|
#include "nsRect.h" // for nsIntRect
|
||||||
#include "nsSize.h" // for nsIntSize
|
#include "nsSize.h" // for nsIntSize
|
||||||
|
#include "mozilla/layers/TiledContentClient.h"
|
||||||
|
|
||||||
class gfxReusableSurfaceWrapper;
|
class gfxReusableSurfaceWrapper;
|
||||||
|
|
||||||
|
@ -24,39 +25,119 @@ namespace layers {
|
||||||
|
|
||||||
class Layer;
|
class Layer;
|
||||||
|
|
||||||
void
|
TiledLayerBufferComposite::TiledLayerBufferComposite()
|
||||||
TiledLayerBufferComposite::Upload(const BasicTiledLayerBuffer* aMainMemoryTiledBuffer,
|
: mFrameResolution(1.0)
|
||||||
const nsIntRegion& aNewValidRegion,
|
, mHasDoubleBufferedTiles(false)
|
||||||
const nsIntRegion& aInvalidateRegion,
|
, mUninitialized(true)
|
||||||
const CSSToScreenScale& aResolution)
|
{}
|
||||||
|
|
||||||
|
TiledLayerBufferComposite::TiledLayerBufferComposite(ISurfaceAllocator* aAllocator,
|
||||||
|
const SurfaceDescriptorTiles& aDescriptor,
|
||||||
|
const nsIntRegion& aOldPaintedRegion)
|
||||||
{
|
{
|
||||||
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
|
mUninitialized = false;
|
||||||
printf_stderr("Upload %i, %i, %i, %i\n", aInvalidateRegion.GetBounds().x, aInvalidateRegion.GetBounds().y, aInvalidateRegion.GetBounds().width, aInvalidateRegion.GetBounds().height);
|
mHasDoubleBufferedTiles = false;
|
||||||
long start = PR_IntervalNow();
|
mValidRegion = aDescriptor.validRegion();
|
||||||
#endif
|
mPaintedRegion = aDescriptor.paintedRegion();
|
||||||
|
mRetainedWidth = aDescriptor.retainedWidth();
|
||||||
|
mRetainedHeight = aDescriptor.retainedHeight();
|
||||||
|
mResolution = aDescriptor.resolution();
|
||||||
|
|
||||||
mFrameResolution = aResolution;
|
// Combine any valid content that wasn't already uploaded
|
||||||
mMainMemoryTiledBuffer = aMainMemoryTiledBuffer;
|
nsIntRegion oldPaintedRegion(aOldPaintedRegion);
|
||||||
Update(aNewValidRegion, aInvalidateRegion);
|
oldPaintedRegion.And(oldPaintedRegion, mValidRegion);
|
||||||
mMainMemoryTiledBuffer = nullptr;
|
mPaintedRegion.Or(mPaintedRegion, oldPaintedRegion);
|
||||||
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
|
|
||||||
if (PR_IntervalNow() - start > 10) {
|
const InfallibleTArray<TileDescriptor>& tiles = aDescriptor.tiles();
|
||||||
printf_stderr("Time to upload %i\n", PR_IntervalNow() - start);
|
for(size_t i = 0; i < tiles.Length(); i++) {
|
||||||
|
RefPtr<TextureHost> texture;
|
||||||
|
const TileDescriptor& tileDesc = tiles[i];
|
||||||
|
switch (tileDesc.type()) {
|
||||||
|
case TileDescriptor::TTexturedTileDescriptor : {
|
||||||
|
texture = TextureHost::AsTextureHost(tileDesc.get_TexturedTileDescriptor().textureParent());
|
||||||
|
const TileLock& ipcLock = tileDesc.get_TexturedTileDescriptor().sharedLock();
|
||||||
|
nsRefPtr<gfxSharedReadLock> sharedLock;
|
||||||
|
if (ipcLock.type() == TileLock::TShmem) {
|
||||||
|
sharedLock = gfxShmSharedReadLock::Open(aAllocator, ipcLock.get_Shmem());
|
||||||
|
} else {
|
||||||
|
sharedLock = reinterpret_cast<gfxMemorySharedReadLock*>(ipcLock.get_uintptr_t());
|
||||||
|
// The corresponding AddRef is in TiledClient::GetTileDescriptor
|
||||||
|
sharedLock->Release();
|
||||||
|
}
|
||||||
|
MOZ_ASSERT(sharedLock);
|
||||||
|
if (sharedLock) {
|
||||||
|
mRetainedTiles.AppendElement(TileHost(sharedLock, texture));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
NS_WARNING("Unrecognised tile descriptor type");
|
||||||
|
// Fall through
|
||||||
|
case TileDescriptor::TPlaceholderTileDescriptor :
|
||||||
|
mRetainedTiles.AppendElement(GetPlaceholderTile());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (texture && !texture->HasInternalBuffer()) {
|
||||||
|
mHasDoubleBufferedTiles = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TiledTexture
|
void
|
||||||
TiledLayerBufferComposite::ValidateTile(TiledTexture aTile,
|
TiledLayerBufferComposite::ReadUnlock()
|
||||||
|
{
|
||||||
|
if (!IsValid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < mRetainedTiles.Length(); i++) {
|
||||||
|
mRetainedTiles[i].ReadUnlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TiledLayerBufferComposite::ReleaseTextureHosts()
|
||||||
|
{
|
||||||
|
if (!IsValid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < mRetainedTiles.Length(); i++) {
|
||||||
|
mRetainedTiles[i].mTextureHost = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TiledLayerBufferComposite::Upload()
|
||||||
|
{
|
||||||
|
if(!IsValid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// The TextureClients were created with the TEXTURE_IMMEDIATE_UPLOAD flag,
|
||||||
|
// so calling Update on all the texture hosts will perform the texture upload.
|
||||||
|
Update(mValidRegion, mPaintedRegion);
|
||||||
|
ClearPaintedRegion();
|
||||||
|
}
|
||||||
|
|
||||||
|
TileHost
|
||||||
|
TiledLayerBufferComposite::ValidateTile(TileHost aTile,
|
||||||
const nsIntPoint& aTileOrigin,
|
const nsIntPoint& aTileOrigin,
|
||||||
const nsIntRegion& aDirtyRect)
|
const nsIntRegion& aDirtyRect)
|
||||||
{
|
{
|
||||||
|
if (aTile.IsPlaceholderTile()) {
|
||||||
|
NS_WARNING("Placeholder tile encountered in painted region");
|
||||||
|
return aTile;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
|
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
|
||||||
printf_stderr("Upload tile %i, %i\n", aTileOrigin.x, aTileOrigin.y);
|
printf_stderr("Upload tile %i, %i\n", aTileOrigin.x, aTileOrigin.y);
|
||||||
long start = PR_IntervalNow();
|
long start = PR_IntervalNow();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
aTile.Validate(mMainMemoryTiledBuffer->GetTile(aTileOrigin).GetSurface(), mCompositor, GetTileLength());
|
MOZ_ASSERT(aTile.mTextureHost->GetFlags() & TEXTURE_IMMEDIATE_UPLOAD);
|
||||||
|
// We possibly upload the entire texture contents here. This is a purposeful
|
||||||
|
// decision, as sub-image upload can often be slow and/or unreliable, but
|
||||||
|
// we may want to reevaluate this in the future.
|
||||||
|
// For !HasInternalBuffer() textures, this is likely a no-op.
|
||||||
|
aTile.mTextureHost->Updated(nullptr);
|
||||||
|
|
||||||
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
|
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
|
||||||
if (PR_IntervalNow() - start > 1) {
|
if (PR_IntervalNow() - start > 1) {
|
||||||
|
@ -66,6 +147,57 @@ TiledLayerBufferComposite::ValidateTile(TiledTexture aTile,
|
||||||
return aTile;
|
return aTile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
TiledLayerBufferComposite::SetCompositor(Compositor* aCompositor)
|
||||||
|
{
|
||||||
|
if (!IsValid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < mRetainedTiles.Length(); i++) {
|
||||||
|
if (mRetainedTiles[i].IsPlaceholderTile()) continue;
|
||||||
|
mRetainedTiles[i].mTextureHost->SetCompositor(aCompositor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TiledContentHost::TiledContentHost(const TextureInfo& aTextureInfo)
|
||||||
|
: ContentHost(aTextureInfo)
|
||||||
|
, mTiledBuffer(TiledLayerBufferComposite())
|
||||||
|
, mLowPrecisionTiledBuffer(TiledLayerBufferComposite())
|
||||||
|
, mOldTiledBuffer(TiledLayerBufferComposite())
|
||||||
|
, mOldLowPrecisionTiledBuffer(TiledLayerBufferComposite())
|
||||||
|
, mPendingUpload(false)
|
||||||
|
, mPendingLowPrecisionUpload(false)
|
||||||
|
{
|
||||||
|
MOZ_COUNT_CTOR(TiledContentHost);
|
||||||
|
}
|
||||||
|
|
||||||
|
TiledContentHost::~TiledContentHost()
|
||||||
|
{
|
||||||
|
MOZ_COUNT_DTOR(TiledContentHost);
|
||||||
|
|
||||||
|
// Unlock any buffers that may still be locked. If we have a pending upload,
|
||||||
|
// we will need to unlock the buffer that was about to be uploaded.
|
||||||
|
// If a buffer that was being composited had double-buffered tiles, we will
|
||||||
|
// need to unlock that buffer too.
|
||||||
|
if (mPendingUpload) {
|
||||||
|
mTiledBuffer.ReadUnlock();
|
||||||
|
if (mOldTiledBuffer.HasDoubleBufferedTiles()) {
|
||||||
|
mOldTiledBuffer.ReadUnlock();
|
||||||
|
}
|
||||||
|
} else if (mTiledBuffer.HasDoubleBufferedTiles()) {
|
||||||
|
mTiledBuffer.ReadUnlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mPendingLowPrecisionUpload) {
|
||||||
|
mLowPrecisionTiledBuffer.ReadUnlock();
|
||||||
|
if (mOldLowPrecisionTiledBuffer.HasDoubleBufferedTiles()) {
|
||||||
|
mOldLowPrecisionTiledBuffer.ReadUnlock();
|
||||||
|
}
|
||||||
|
} else if (mLowPrecisionTiledBuffer.HasDoubleBufferedTiles()) {
|
||||||
|
mLowPrecisionTiledBuffer.ReadUnlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TiledContentHost::Attach(Layer* aLayer,
|
TiledContentHost::Attach(Layer* aLayer,
|
||||||
Compositor* aCompositor,
|
Compositor* aCompositor,
|
||||||
|
@ -76,70 +208,41 @@ TiledContentHost::Attach(Layer* aLayer,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
TiledContentHost::PaintedTiledLayerBuffer(ISurfaceAllocator* aAllocator,
|
TiledContentHost::UseTiledLayerBuffer(ISurfaceAllocator* aAllocator,
|
||||||
const SurfaceDescriptorTiles& aTiledDescriptor)
|
const SurfaceDescriptorTiles& aTiledDescriptor)
|
||||||
{
|
{
|
||||||
if (aTiledDescriptor.resolution() < 1) {
|
if (aTiledDescriptor.resolution() < 1) {
|
||||||
mLowPrecisionMainMemoryTiledBuffer = BasicTiledLayerBuffer::OpenDescriptor(aAllocator, aTiledDescriptor, nullptr);
|
if (mPendingLowPrecisionUpload) {
|
||||||
mLowPrecisionRegionToUpload.Or(mLowPrecisionRegionToUpload,
|
mLowPrecisionTiledBuffer.ReadUnlock();
|
||||||
mLowPrecisionMainMemoryTiledBuffer.GetPaintedRegion());
|
} else {
|
||||||
mLowPrecisionMainMemoryTiledBuffer.ClearPaintedRegion();
|
mPendingLowPrecisionUpload = true;
|
||||||
mPendingLowPrecisionUpload = true;
|
// If the old buffer has double-buffered tiles, hang onto it so we can
|
||||||
|
// unlock it after we've composited the new buffer.
|
||||||
|
// We only need to hang onto the locks, but not the textures.
|
||||||
|
// Releasing the textures here can help prevent a memory spike in the
|
||||||
|
// situation that the client starts rendering new content before we get
|
||||||
|
// to composite the new buffer.
|
||||||
|
if (mLowPrecisionTiledBuffer.HasDoubleBufferedTiles()) {
|
||||||
|
mOldLowPrecisionTiledBuffer = mLowPrecisionTiledBuffer;
|
||||||
|
mOldLowPrecisionTiledBuffer.ReleaseTextureHosts();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mLowPrecisionTiledBuffer =
|
||||||
|
TiledLayerBufferComposite(aAllocator, aTiledDescriptor,
|
||||||
|
mLowPrecisionTiledBuffer.GetPaintedRegion());
|
||||||
|
} else {
|
||||||
|
if (mPendingUpload) {
|
||||||
|
mTiledBuffer.ReadUnlock();
|
||||||
} else {
|
} else {
|
||||||
mMainMemoryTiledBuffer = BasicTiledLayerBuffer::OpenDescriptor(aAllocator, aTiledDescriptor, nullptr);
|
|
||||||
mRegionToUpload.Or(mRegionToUpload, mMainMemoryTiledBuffer.GetPaintedRegion());
|
|
||||||
mMainMemoryTiledBuffer.ClearPaintedRegion();
|
|
||||||
mPendingUpload = true;
|
mPendingUpload = true;
|
||||||
|
if (mTiledBuffer.HasDoubleBufferedTiles()) {
|
||||||
|
mOldTiledBuffer = mTiledBuffer;
|
||||||
|
mOldTiledBuffer.ReleaseTextureHosts();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mTiledBuffer = TiledLayerBufferComposite(aAllocator, aTiledDescriptor,
|
||||||
void
|
mTiledBuffer.GetPaintedRegion());
|
||||||
TiledContentHost::ProcessLowPrecisionUploadQueue()
|
|
||||||
{
|
|
||||||
if (!mPendingLowPrecisionUpload) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mLowPrecisionRegionToUpload.And(mLowPrecisionRegionToUpload,
|
|
||||||
mLowPrecisionMainMemoryTiledBuffer.GetValidRegion());
|
|
||||||
mLowPrecisionVideoMemoryTiledBuffer.SetResolution(
|
|
||||||
mLowPrecisionMainMemoryTiledBuffer.GetResolution());
|
|
||||||
// It's assumed that the video memory tiled buffer has an up-to-date
|
|
||||||
// frame resolution. As it's always updated first when zooming, this
|
|
||||||
// should always be true.
|
|
||||||
mLowPrecisionVideoMemoryTiledBuffer.Upload(&mLowPrecisionMainMemoryTiledBuffer,
|
|
||||||
mLowPrecisionMainMemoryTiledBuffer.GetValidRegion(),
|
|
||||||
mLowPrecisionRegionToUpload,
|
|
||||||
mVideoMemoryTiledBuffer.GetFrameResolution());
|
|
||||||
nsIntRegion validRegion = mLowPrecisionVideoMemoryTiledBuffer.GetValidRegion();
|
|
||||||
|
|
||||||
mLowPrecisionMainMemoryTiledBuffer = BasicTiledLayerBuffer();
|
|
||||||
mLowPrecisionRegionToUpload = nsIntRegion();
|
|
||||||
mPendingLowPrecisionUpload = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TiledContentHost::ProcessUploadQueue(nsIntRegion* aNewValidRegion,
|
|
||||||
TiledLayerProperties* aLayerProperties)
|
|
||||||
{
|
|
||||||
if (!mPendingUpload)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// If we coalesce uploads while the layers' valid region is changing we will
|
|
||||||
// end up trying to upload area outside of the valid region. (bug 756555)
|
|
||||||
mRegionToUpload.And(mRegionToUpload, mMainMemoryTiledBuffer.GetValidRegion());
|
|
||||||
|
|
||||||
mVideoMemoryTiledBuffer.Upload(&mMainMemoryTiledBuffer,
|
|
||||||
mMainMemoryTiledBuffer.GetValidRegion(),
|
|
||||||
mRegionToUpload, aLayerProperties->mEffectiveResolution);
|
|
||||||
|
|
||||||
*aNewValidRegion = mVideoMemoryTiledBuffer.GetValidRegion();
|
|
||||||
|
|
||||||
// Release all the tiles by replacing the tile buffer with an empty
|
|
||||||
// tiled buffer.
|
|
||||||
mMainMemoryTiledBuffer = BasicTiledLayerBuffer();
|
|
||||||
mRegionToUpload = nsIntRegion();
|
|
||||||
mPendingUpload = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -153,24 +256,51 @@ TiledContentHost::Composite(EffectChain& aEffectChain,
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aLayerProperties, "aLayerProperties required for TiledContentHost");
|
MOZ_ASSERT(aLayerProperties, "aLayerProperties required for TiledContentHost");
|
||||||
|
|
||||||
// note that ProcessUploadQueue updates the valid region which is then used by
|
|
||||||
// the RenderLayerBuffer calls below and then sent back to the layer.
|
|
||||||
ProcessUploadQueue(&aLayerProperties->mValidRegion, aLayerProperties);
|
|
||||||
ProcessLowPrecisionUploadQueue();
|
|
||||||
|
|
||||||
// Render valid tiles.
|
// Render valid tiles.
|
||||||
nsIntRect visibleRect = aVisibleRegion->GetBounds();
|
nsIntRect visibleRect = aVisibleRegion->GetBounds();
|
||||||
|
|
||||||
RenderLayerBuffer(mLowPrecisionVideoMemoryTiledBuffer,
|
if (mPendingUpload) {
|
||||||
mLowPrecisionVideoMemoryTiledBuffer.GetValidRegion(), aEffectChain, aOpacity,
|
mTiledBuffer.SetCompositor(mCompositor);
|
||||||
|
mTiledBuffer.Upload();
|
||||||
|
|
||||||
|
// For a single-buffered tiled buffer, Upload will upload the shared memory
|
||||||
|
// surface to texture memory and we no longer need to read from them.
|
||||||
|
if (!mTiledBuffer.HasDoubleBufferedTiles()) {
|
||||||
|
mTiledBuffer.ReadUnlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mPendingLowPrecisionUpload) {
|
||||||
|
mLowPrecisionTiledBuffer.SetCompositor(mCompositor);
|
||||||
|
mLowPrecisionTiledBuffer.Upload();
|
||||||
|
|
||||||
|
if (!mLowPrecisionTiledBuffer.HasDoubleBufferedTiles()) {
|
||||||
|
mLowPrecisionTiledBuffer.ReadUnlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RenderLayerBuffer(mLowPrecisionTiledBuffer,
|
||||||
|
mLowPrecisionTiledBuffer.GetValidRegion(), aEffectChain, aOpacity,
|
||||||
aFilter, aClipRect, aLayerProperties->mValidRegion, visibleRect, aTransform);
|
aFilter, aClipRect, aLayerProperties->mValidRegion, visibleRect, aTransform);
|
||||||
RenderLayerBuffer(mVideoMemoryTiledBuffer, aLayerProperties->mValidRegion, aEffectChain, aOpacity,
|
RenderLayerBuffer(mTiledBuffer, aLayerProperties->mValidRegion, aEffectChain, aOpacity,
|
||||||
aFilter, aClipRect, nsIntRegion(), visibleRect, aTransform);
|
aFilter, aClipRect, nsIntRegion(), visibleRect, aTransform);
|
||||||
|
|
||||||
|
// Now release the old buffer if it had double-buffered tiles, as we can
|
||||||
|
// guarantee that they're no longer on the screen (and so any locks that may
|
||||||
|
// have been held have been released).
|
||||||
|
if (mPendingUpload && mOldTiledBuffer.HasDoubleBufferedTiles()) {
|
||||||
|
mOldTiledBuffer.ReadUnlock();
|
||||||
|
mOldTiledBuffer = TiledLayerBufferComposite();
|
||||||
|
}
|
||||||
|
if (mPendingLowPrecisionUpload && mOldLowPrecisionTiledBuffer.HasDoubleBufferedTiles()) {
|
||||||
|
mOldLowPrecisionTiledBuffer.ReadUnlock();
|
||||||
|
mOldLowPrecisionTiledBuffer = TiledLayerBufferComposite();
|
||||||
|
}
|
||||||
|
mPendingUpload = mPendingLowPrecisionUpload = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TiledContentHost::RenderTile(const TiledTexture& aTile,
|
TiledContentHost::RenderTile(const TileHost& aTile,
|
||||||
EffectChain& aEffectChain,
|
EffectChain& aEffectChain,
|
||||||
float aOpacity,
|
float aOpacity,
|
||||||
const gfx::Matrix4x4& aTransform,
|
const gfx::Matrix4x4& aTransform,
|
||||||
|
@ -180,19 +310,38 @@ TiledContentHost::RenderTile(const TiledTexture& aTile,
|
||||||
const nsIntPoint& aTextureOffset,
|
const nsIntPoint& aTextureOffset,
|
||||||
const nsIntSize& aTextureBounds)
|
const nsIntSize& aTextureBounds)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aTile.mDeprecatedTextureHost, "Trying to render a placeholder tile?");
|
if (aTile.IsPlaceholderTile()) {
|
||||||
|
// This shouldn't ever happen, but let's fail semi-gracefully. No need
|
||||||
|
// to warn, the texture update would have already caught this.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIntRect screenBounds = aScreenRegion.GetBounds();
|
||||||
|
Matrix mat = aTransform.As2D();
|
||||||
|
Rect quad(screenBounds.x, screenBounds.y, screenBounds.width, screenBounds.height);
|
||||||
|
quad = mat.TransformBounds(quad);
|
||||||
|
|
||||||
|
if (!quad.Intersects(aClipRect)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AutoLockTextureHost autoLock(aTile.mTextureHost);
|
||||||
|
if (autoLock.Failed()) {
|
||||||
|
NS_WARNING("Failed to lock tile");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
RefPtr<NewTextureSource> source = aTile.mTextureHost->GetTextureSources();
|
||||||
|
if (!source) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
RefPtr<TexturedEffect> effect =
|
RefPtr<TexturedEffect> effect =
|
||||||
CreateTexturedEffect(aTile.mDeprecatedTextureHost, aFilter);
|
CreateTexturedEffect(aTile.mTextureHost->GetFormat(), source, aFilter);
|
||||||
if (!effect) {
|
if (!effect) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aTile.mDeprecatedTextureHost->Lock()) {
|
|
||||||
aEffectChain.mPrimaryEffect = effect;
|
aEffectChain.mPrimaryEffect = effect;
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsIntRegionRectIterator it(aScreenRegion);
|
nsIntRegionRectIterator it(aScreenRegion);
|
||||||
for (const nsIntRect* rect = it.Next(); rect != nullptr; rect = it.Next()) {
|
for (const nsIntRect* rect = it.Next(); rect != nullptr; rect = it.Next()) {
|
||||||
|
@ -208,8 +357,6 @@ TiledContentHost::RenderTile(const TiledTexture& aTile,
|
||||||
}
|
}
|
||||||
mCompositor->DrawDiagnostics(DIAGNOSTIC_CONTENT|DIAGNOSTIC_TILE,
|
mCompositor->DrawDiagnostics(DIAGNOSTIC_CONTENT|DIAGNOSTIC_TILE,
|
||||||
aScreenRegion, aClipRect, aTransform);
|
aScreenRegion, aClipRect, aTransform);
|
||||||
|
|
||||||
aTile.mDeprecatedTextureHost->Unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -231,9 +378,9 @@ TiledContentHost::RenderLayerBuffer(TiledLayerBufferComposite& aLayerBuffer,
|
||||||
gfx::Size layerScale(1, 1);
|
gfx::Size layerScale(1, 1);
|
||||||
// We assume that the current frame resolution is the one used in our primary
|
// We assume that the current frame resolution is the one used in our primary
|
||||||
// layer buffer. Compensate for a changing frame resolution.
|
// layer buffer. Compensate for a changing frame resolution.
|
||||||
if (aLayerBuffer.GetFrameResolution() != mVideoMemoryTiledBuffer.GetFrameResolution()) {
|
if (aLayerBuffer.GetFrameResolution() != mTiledBuffer.GetFrameResolution()) {
|
||||||
const CSSToScreenScale& layerResolution = aLayerBuffer.GetFrameResolution();
|
const CSSToScreenScale& layerResolution = aLayerBuffer.GetFrameResolution();
|
||||||
const CSSToScreenScale& localResolution = mVideoMemoryTiledBuffer.GetFrameResolution();
|
const CSSToScreenScale& localResolution = mTiledBuffer.GetFrameResolution();
|
||||||
layerScale.width = layerScale.height = layerResolution.scale / localResolution.scale;
|
layerScale.width = layerScale.height = layerResolution.scale / localResolution.scale;
|
||||||
aVisibleRect.ScaleRoundOut(layerScale.width, layerScale.height);
|
aVisibleRect.ScaleRoundOut(layerScale.width, layerScale.height);
|
||||||
}
|
}
|
||||||
|
@ -257,7 +404,7 @@ TiledContentHost::RenderLayerBuffer(TiledLayerBufferComposite& aLayerBuffer,
|
||||||
h = aVisibleRect.y + aVisibleRect.height - y;
|
h = aVisibleRect.y + aVisibleRect.height - y;
|
||||||
}
|
}
|
||||||
|
|
||||||
TiledTexture tileTexture = aLayerBuffer.
|
TileHost tileTexture = aLayerBuffer.
|
||||||
GetTile(nsIntPoint(aLayerBuffer.RoundDownToTileEdge(x),
|
GetTile(nsIntPoint(aLayerBuffer.RoundDownToTileEdge(x),
|
||||||
aLayerBuffer.RoundDownToTileEdge(y)));
|
aLayerBuffer.RoundDownToTileEdge(y)));
|
||||||
if (tileTexture != aLayerBuffer.GetPlaceholderTile()) {
|
if (tileTexture != aLayerBuffer.GetPlaceholderTile()) {
|
||||||
|
@ -292,23 +439,6 @@ TiledContentHost::RenderLayerBuffer(TiledLayerBufferComposite& aLayerBuffer,
|
||||||
rect, aClipRect, aTransform);
|
rect, aClipRect, aTransform);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
TiledTexture::Validate(gfxReusableSurfaceWrapper* aReusableSurface, Compositor* aCompositor, uint16_t aSize)
|
|
||||||
{
|
|
||||||
TextureFlags flags = 0;
|
|
||||||
if (!mDeprecatedTextureHost) {
|
|
||||||
// convert placeholder tile to a real tile
|
|
||||||
mDeprecatedTextureHost = DeprecatedTextureHost::CreateDeprecatedTextureHost(SurfaceDescriptor::Tnull_t,
|
|
||||||
TEXTURE_HOST_TILED,
|
|
||||||
flags,
|
|
||||||
nullptr);
|
|
||||||
mDeprecatedTextureHost->SetCompositor(aCompositor);
|
|
||||||
flags |= TEXTURE_NEW_TILE;
|
|
||||||
}
|
|
||||||
|
|
||||||
mDeprecatedTextureHost->Update(aReusableSurface, flags, gfx::IntSize(aSize, aSize));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TiledContentHost::PrintInfo(nsACString& aTo, const char* aPrefix)
|
TiledContentHost::PrintInfo(nsACString& aTo, const char* aPrefix)
|
||||||
{
|
{
|
||||||
|
@ -327,15 +457,19 @@ TiledContentHost::Dump(FILE* aFile,
|
||||||
aFile = stderr;
|
aFile = stderr;
|
||||||
}
|
}
|
||||||
|
|
||||||
TiledLayerBufferComposite::Iterator it = mVideoMemoryTiledBuffer.TilesBegin();
|
TiledLayerBufferComposite::Iterator it = mTiledBuffer.TilesBegin();
|
||||||
TiledLayerBufferComposite::Iterator stop = mVideoMemoryTiledBuffer.TilesEnd();
|
TiledLayerBufferComposite::Iterator stop = mTiledBuffer.TilesEnd();
|
||||||
if (aDumpHtml) {
|
if (aDumpHtml) {
|
||||||
fprintf_stderr(aFile, "<ul>");
|
fprintf_stderr(aFile, "<ul>");
|
||||||
}
|
}
|
||||||
for (;it != stop; ++it) {
|
for (;it != stop; ++it) {
|
||||||
fprintf_stderr(aFile, "%s", aPrefix);
|
fprintf_stderr(aFile, "%s", aPrefix);
|
||||||
fprintf_stderr(aFile, aDumpHtml ? "<li> <a href=" : "Tile ");
|
fprintf_stderr(aFile, aDumpHtml ? "<li> <a href=" : "Tile ");
|
||||||
DumpDeprecatedTextureHost(aFile, it->mDeprecatedTextureHost);
|
if (it->IsPlaceholderTile()) {
|
||||||
|
fprintf_stderr(aFile, "empty tile");
|
||||||
|
} else {
|
||||||
|
DumpTextureHost(aFile, it->mTextureHost);
|
||||||
|
}
|
||||||
fprintf_stderr(aFile, aDumpHtml ? " >Tile</a></li>" : " ");
|
fprintf_stderr(aFile, aDumpHtml ? " >Tile</a></li>" : " ");
|
||||||
}
|
}
|
||||||
if (aDumpHtml) {
|
if (aDumpHtml) {
|
||||||
|
|
|
@ -47,132 +47,138 @@ class TiledThebesLayerComposite;
|
||||||
struct EffectChain;
|
struct EffectChain;
|
||||||
|
|
||||||
|
|
||||||
class TiledTexture {
|
class TileHost {
|
||||||
public:
|
public:
|
||||||
// Constructs a placeholder TiledTexture. See the comments above
|
// Constructs a placeholder TileHost. See the comments above
|
||||||
// TiledLayerBuffer for more information on what this is used for;
|
// TiledLayerBuffer for more information on what this is used for;
|
||||||
// essentially, this is a sentinel used to represent an invalid or blank
|
// essentially, this is a sentinel used to represent an invalid or blank
|
||||||
// tile.
|
// tile.
|
||||||
TiledTexture()
|
TileHost()
|
||||||
: mDeprecatedTextureHost(nullptr)
|
: mSharedLock(nullptr)
|
||||||
|
, mTextureHost(nullptr)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
// Constructs a TiledTexture from a DeprecatedTextureHost.
|
// Constructs a TileHost from a gfxSharedReadLock and TextureHost.
|
||||||
TiledTexture(DeprecatedTextureHost* aDeprecatedTextureHost)
|
TileHost(gfxSharedReadLock* aSharedLock,
|
||||||
: mDeprecatedTextureHost(aDeprecatedTextureHost)
|
TextureHost* aTextureHost)
|
||||||
|
: mSharedLock(aSharedLock)
|
||||||
|
, mTextureHost(aTextureHost)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
TiledTexture(const TiledTexture& o) {
|
TileHost(const TileHost& o) {
|
||||||
mDeprecatedTextureHost = o.mDeprecatedTextureHost;
|
mTextureHost = o.mTextureHost;
|
||||||
|
mSharedLock = o.mSharedLock;
|
||||||
}
|
}
|
||||||
TiledTexture& operator=(const TiledTexture& o) {
|
TileHost& operator=(const TileHost& o) {
|
||||||
if (this == &o) {
|
if (this == &o) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
mDeprecatedTextureHost = o.mDeprecatedTextureHost;
|
mTextureHost = o.mTextureHost;
|
||||||
|
mSharedLock = o.mSharedLock;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Validate(gfxReusableSurfaceWrapper* aReusableSurface, Compositor* aCompositor, uint16_t aSize);
|
bool operator== (const TileHost& o) const {
|
||||||
|
return mTextureHost == o.mTextureHost;
|
||||||
bool operator== (const TiledTexture& o) const {
|
|
||||||
if (!mDeprecatedTextureHost || !o.mDeprecatedTextureHost) {
|
|
||||||
return mDeprecatedTextureHost == o.mDeprecatedTextureHost;
|
|
||||||
}
|
}
|
||||||
return *mDeprecatedTextureHost == *o.mDeprecatedTextureHost;
|
bool operator!= (const TileHost& o) const {
|
||||||
}
|
return mTextureHost != o.mTextureHost;
|
||||||
bool operator!= (const TiledTexture& o) const {
|
|
||||||
if (!mDeprecatedTextureHost || !o.mDeprecatedTextureHost) {
|
|
||||||
return mDeprecatedTextureHost != o.mDeprecatedTextureHost;
|
|
||||||
}
|
|
||||||
return *mDeprecatedTextureHost != *o.mDeprecatedTextureHost;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<DeprecatedTextureHost> mDeprecatedTextureHost;
|
bool IsPlaceholderTile() const { return mTextureHost == nullptr; }
|
||||||
|
|
||||||
|
void ReadUnlock() {
|
||||||
|
// Warn if we have a texture host, but no corresponding lock.
|
||||||
|
NS_WARN_IF_FALSE(mTextureHost == nullptr || mSharedLock != nullptr,
|
||||||
|
"ReadUnlock with no gfxSharedReadLock");
|
||||||
|
if (mSharedLock) {
|
||||||
|
mSharedLock->ReadUnlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<gfxSharedReadLock> mSharedLock;
|
||||||
|
RefPtr<TextureHost> mTextureHost;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TiledLayerBufferComposite
|
class TiledLayerBufferComposite
|
||||||
: public TiledLayerBuffer<TiledLayerBufferComposite, TiledTexture>
|
: public TiledLayerBuffer<TiledLayerBufferComposite, TileHost>
|
||||||
{
|
{
|
||||||
friend class TiledLayerBuffer<TiledLayerBufferComposite, TiledTexture>;
|
friend class TiledLayerBuffer<TiledLayerBufferComposite, TileHost>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef TiledLayerBuffer<TiledLayerBufferComposite, TiledTexture>::Iterator Iterator;
|
typedef TiledLayerBuffer<TiledLayerBufferComposite, TileHost>::Iterator Iterator;
|
||||||
TiledLayerBufferComposite()
|
|
||||||
: mCompositor(nullptr)
|
|
||||||
{}
|
|
||||||
|
|
||||||
void Upload(const BasicTiledLayerBuffer* aMainMemoryTiledBuffer,
|
TiledLayerBufferComposite();
|
||||||
const nsIntRegion& aNewValidRegion,
|
TiledLayerBufferComposite(ISurfaceAllocator* aAllocator,
|
||||||
const nsIntRegion& aInvalidateRegion,
|
const SurfaceDescriptorTiles& aDescriptor,
|
||||||
const CSSToScreenScale& aResolution);
|
const nsIntRegion& aOldPaintedRegion);
|
||||||
|
|
||||||
TiledTexture GetPlaceholderTile() const { return TiledTexture(); }
|
TileHost GetPlaceholderTile() const { return TileHost(); }
|
||||||
|
|
||||||
// Stores the absolute resolution of the containing frame, calculated
|
// Stores the absolute resolution of the containing frame, calculated
|
||||||
// by the sum of the resolutions of all parent layers' FrameMetrics.
|
// by the sum of the resolutions of all parent layers' FrameMetrics.
|
||||||
const CSSToScreenScale& GetFrameResolution() { return mFrameResolution; }
|
const CSSToScreenScale& GetFrameResolution() { return mFrameResolution; }
|
||||||
|
|
||||||
void SetCompositor(Compositor* aCompositor)
|
void ReadUnlock();
|
||||||
{
|
|
||||||
mCompositor = aCompositor;
|
void ReleaseTextureHosts();
|
||||||
}
|
|
||||||
|
/**
|
||||||
|
* This will synchronously upload any necessary texture contents, making the
|
||||||
|
* sources immediately available for compositing. For texture hosts that
|
||||||
|
* don't have an internal buffer, this is unlikely to actually do anything.
|
||||||
|
*/
|
||||||
|
void Upload();
|
||||||
|
|
||||||
|
void SetCompositor(Compositor* aCompositor);
|
||||||
|
|
||||||
|
bool HasDoubleBufferedTiles() { return mHasDoubleBufferedTiles; }
|
||||||
|
|
||||||
|
bool IsValid() const { return !mUninitialized; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TiledTexture ValidateTile(TiledTexture aTile,
|
TileHost ValidateTile(TileHost aTile,
|
||||||
const nsIntPoint& aTileRect,
|
const nsIntPoint& aTileRect,
|
||||||
const nsIntRegion& dirtyRect);
|
const nsIntRegion& dirtyRect);
|
||||||
|
|
||||||
// do nothing, the desctructor in the texture host takes care of releasing resources
|
// do nothing, the desctructor in the texture host takes care of releasing resources
|
||||||
void ReleaseTile(TiledTexture aTile) {}
|
void ReleaseTile(TileHost aTile) {}
|
||||||
|
|
||||||
void SwapTiles(TiledTexture& aTileA, TiledTexture& aTileB) {
|
void SwapTiles(TileHost& aTileA, TileHost& aTileB) { std::swap(aTileA, aTileB); }
|
||||||
std::swap(aTileA, aTileB);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Compositor* mCompositor;
|
|
||||||
const BasicTiledLayerBuffer* mMainMemoryTiledBuffer;
|
|
||||||
CSSToScreenScale mFrameResolution;
|
CSSToScreenScale mFrameResolution;
|
||||||
|
bool mHasDoubleBufferedTiles;
|
||||||
|
bool mUninitialized;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ContentHost for tiled Thebes layers. Since tiled layers are special snow
|
* ContentHost for tiled Thebes layers. Since tiled layers are special snow
|
||||||
* flakes, we don't call UpdateThebes or AddTextureHost, etc. We do call Composite
|
* flakes, we have a unique update process. All the textures that back the
|
||||||
* in the usual way though.
|
* tiles are added in the usual way, but Updated is called on the host side
|
||||||
*
|
* in response to a message that describes the transaction for every tile.
|
||||||
* There is no corresponding content client - on the client side we use a
|
* Composition happens in the normal way.
|
||||||
* BasicTiledLayerBuffer owned by a BasicTiledThebesLayer. On the host side, we
|
|
||||||
* just use a regular ThebesLayerComposite, but with a tiled content host.
|
|
||||||
*
|
*
|
||||||
* TiledContentHost has a TiledLayerBufferComposite which keeps hold of the tiles.
|
* TiledContentHost has a TiledLayerBufferComposite which keeps hold of the tiles.
|
||||||
* Each tile has a reference to a texture host. During the layers transaction, we
|
* Each tile has a reference to a texture host. During the layers transaction, we
|
||||||
* receive a copy of the client-side tile buffer (PaintedTiledLayerBuffer). This is
|
* receive a list of descriptors for the client-side tile buffer tiles
|
||||||
* copied into the main memory tile buffer and then deleted. Copying copies tiles,
|
* (UseTiledLayerBuffer). If we receive two transactions before a composition,
|
||||||
* but we only copy references to the underlying texture clients.
|
* we immediately unlock and discard the unused buffer.
|
||||||
*
|
*
|
||||||
* When the content host is composited, we first upload any pending tiles
|
* When the content host is composited, we first validate the TiledLayerBuffer
|
||||||
* (Process*UploadQueue), then render (RenderLayerBuffer). The former calls Validate
|
* (Upload), which calls Updated on each tile's texture host to make sure the
|
||||||
* on the tile (via ValidateTile and Update), that calls Update on the texture host,
|
* texture data has been uploaded. For single-buffered tiles, we unlock at this
|
||||||
* which works as for regular texture hosts. Rendering takes us to RenderTile which
|
* point, for double-buffered tiles we unlock and discard the last composited
|
||||||
|
* buffer after compositing a new one. Rendering takes us to RenderTile which
|
||||||
* is similar to Composite for non-tiled ContentHosts.
|
* is similar to Composite for non-tiled ContentHosts.
|
||||||
*/
|
*/
|
||||||
class TiledContentHost : public ContentHost,
|
class TiledContentHost : public ContentHost,
|
||||||
public TiledLayerComposer
|
public TiledLayerComposer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TiledContentHost(const TextureInfo& aTextureInfo)
|
TiledContentHost(const TextureInfo& aTextureInfo);
|
||||||
: ContentHost(aTextureInfo)
|
|
||||||
, mPendingUpload(false)
|
|
||||||
, mPendingLowPrecisionUpload(false)
|
|
||||||
{
|
|
||||||
MOZ_COUNT_CTOR(TiledContentHost);
|
|
||||||
}
|
|
||||||
|
|
||||||
~TiledContentHost()
|
~TiledContentHost();
|
||||||
{
|
|
||||||
MOZ_COUNT_DTOR(TiledContentHost);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual LayerRenderState GetRenderState() MOZ_OVERRIDE
|
virtual LayerRenderState GetRenderState() MOZ_OVERRIDE
|
||||||
{
|
{
|
||||||
|
@ -191,14 +197,14 @@ public:
|
||||||
|
|
||||||
const nsIntRegion& GetValidLowPrecisionRegion() const
|
const nsIntRegion& GetValidLowPrecisionRegion() const
|
||||||
{
|
{
|
||||||
return mLowPrecisionVideoMemoryTiledBuffer.GetValidRegion();
|
return mLowPrecisionTiledBuffer.GetValidRegion();
|
||||||
}
|
}
|
||||||
|
|
||||||
void PaintedTiledLayerBuffer(ISurfaceAllocator* aAllocator,
|
void UseTiledLayerBuffer(ISurfaceAllocator* aAllocator,
|
||||||
const SurfaceDescriptorTiles& aTiledDescriptor);
|
const SurfaceDescriptorTiles& aTiledDescriptor);
|
||||||
|
|
||||||
// Renders a single given tile.
|
// Renders a single given tile.
|
||||||
void RenderTile(const TiledTexture& aTile,
|
void RenderTile(const TileHost& aTile,
|
||||||
EffectChain& aEffectChain,
|
EffectChain& aEffectChain,
|
||||||
float aOpacity,
|
float aOpacity,
|
||||||
const gfx::Matrix4x4& aTransform,
|
const gfx::Matrix4x4& aTransform,
|
||||||
|
@ -228,13 +234,6 @@ public:
|
||||||
MOZ_CRASH("Does nothing");
|
MOZ_CRASH("Does nothing");
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE
|
|
||||||
{
|
|
||||||
CompositableHost::SetCompositor(aCompositor);
|
|
||||||
mVideoMemoryTiledBuffer.SetCompositor(aCompositor);
|
|
||||||
mLowPrecisionVideoMemoryTiledBuffer.SetCompositor(aCompositor);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void Attach(Layer* aLayer,
|
virtual void Attach(Layer* aLayer,
|
||||||
Compositor* aCompositor,
|
Compositor* aCompositor,
|
||||||
AttachFlags aFlags = NO_FLAGS) MOZ_OVERRIDE;
|
AttachFlags aFlags = NO_FLAGS) MOZ_OVERRIDE;
|
||||||
|
@ -248,10 +247,6 @@ public:
|
||||||
virtual void PrintInfo(nsACString& aTo, const char* aPrefix);
|
virtual void PrintInfo(nsACString& aTo, const char* aPrefix);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ProcessUploadQueue(nsIntRegion* aNewValidRegion,
|
|
||||||
TiledLayerProperties* aLayerProperties);
|
|
||||||
void ProcessLowPrecisionUploadQueue();
|
|
||||||
|
|
||||||
void RenderLayerBuffer(TiledLayerBufferComposite& aLayerBuffer,
|
void RenderLayerBuffer(TiledLayerBufferComposite& aLayerBuffer,
|
||||||
const nsIntRegion& aValidRegion,
|
const nsIntRegion& aValidRegion,
|
||||||
EffectChain& aEffectChain,
|
EffectChain& aEffectChain,
|
||||||
|
@ -264,12 +259,10 @@ private:
|
||||||
|
|
||||||
void EnsureTileStore() {}
|
void EnsureTileStore() {}
|
||||||
|
|
||||||
nsIntRegion mRegionToUpload;
|
TiledLayerBufferComposite mTiledBuffer;
|
||||||
nsIntRegion mLowPrecisionRegionToUpload;
|
TiledLayerBufferComposite mLowPrecisionTiledBuffer;
|
||||||
BasicTiledLayerBuffer mMainMemoryTiledBuffer;
|
TiledLayerBufferComposite mOldTiledBuffer;
|
||||||
BasicTiledLayerBuffer mLowPrecisionMainMemoryTiledBuffer;
|
TiledLayerBufferComposite mOldLowPrecisionTiledBuffer;
|
||||||
TiledLayerBufferComposite mVideoMemoryTiledBuffer;
|
|
||||||
TiledLayerBufferComposite mLowPrecisionVideoMemoryTiledBuffer;
|
|
||||||
bool mPendingUpload : 1;
|
bool mPendingUpload : 1;
|
||||||
bool mPendingLowPrecisionUpload : 1;
|
bool mPendingLowPrecisionUpload : 1;
|
||||||
};
|
};
|
||||||
|
|
|
@ -709,30 +709,6 @@ LayerManagerD3D10::Render(EndTransactionFlags aFlags)
|
||||||
|
|
||||||
static_cast<LayerD3D10*>(mRoot->ImplData())->RenderLayer();
|
static_cast<LayerD3D10*>(mRoot->ImplData())->RenderLayer();
|
||||||
|
|
||||||
if (!mRegionToClear.IsEmpty()) {
|
|
||||||
float color[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
|
|
||||||
gfx::Matrix4x4 transform;
|
|
||||||
effect()->GetVariableByName("mLayerTransform")->SetRawValue(&transform, 0, 64);
|
|
||||||
effect()->GetVariableByName("fLayerColor")->AsVector()->SetFloatVector(color);
|
|
||||||
|
|
||||||
ID3D10EffectTechnique *technique = effect()->GetTechniqueByName("RenderClearLayer");
|
|
||||||
|
|
||||||
nsIntRegionRectIterator iter(mRegionToClear);
|
|
||||||
const nsIntRect *r;
|
|
||||||
while ((r = iter.Next())) {
|
|
||||||
effect()->GetVariableByName("vLayerQuad")->AsVector()->SetFloatVector(
|
|
||||||
ShaderConstantRectD3D10(
|
|
||||||
(float)r->x,
|
|
||||||
(float)r->y,
|
|
||||||
(float)r->width,
|
|
||||||
(float)r->height)
|
|
||||||
);
|
|
||||||
|
|
||||||
technique->GetPassByIndex(0)->Apply(0);
|
|
||||||
device()->Draw(4, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// See bug 630197 - we have some reasons to believe if an earlier call
|
// See bug 630197 - we have some reasons to believe if an earlier call
|
||||||
// returned an error, the upcoming present call may raise an exception.
|
// returned an error, the upcoming present call may raise an exception.
|
||||||
// This will check if any of the calls done recently has returned an error
|
// This will check if any of the calls done recently has returned an error
|
||||||
|
|
|
@ -448,18 +448,6 @@ technique10 RenderSolidColorLayer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
technique10 RenderClearLayer
|
|
||||||
{
|
|
||||||
pass P0
|
|
||||||
{
|
|
||||||
SetRasterizerState( LayerRast );
|
|
||||||
SetBlendState( NoBlendDual, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
|
|
||||||
SetVertexShader( CompileShader( vs_4_0_level_9_3, LayerQuadVS() ) );
|
|
||||||
SetGeometryShader( NULL );
|
|
||||||
SetPixelShader( CompileShader( ps_4_0_level_9_3, SolidColorShader() ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
technique10 PrepareAlphaExtractionTextures
|
technique10 PrepareAlphaExtractionTextures
|
||||||
{
|
{
|
||||||
pass P0
|
pass P0
|
||||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -45,6 +45,8 @@ public:
|
||||||
|
|
||||||
virtual bool ImplementsLocking() const MOZ_OVERRIDE { return true; }
|
virtual bool ImplementsLocking() const MOZ_OVERRIDE { return true; }
|
||||||
|
|
||||||
|
virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return false; }
|
||||||
|
|
||||||
virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) MOZ_OVERRIDE;
|
virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mSize; }
|
virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mSize; }
|
||||||
|
|
|
@ -261,25 +261,6 @@ LayerManagerD3D9::Render()
|
||||||
|
|
||||||
static_cast<LayerD3D9*>(mRoot->ImplData())->RenderLayer();
|
static_cast<LayerD3D9*>(mRoot->ImplData())->RenderLayer();
|
||||||
|
|
||||||
if (!mRegionToClear.IsEmpty()) {
|
|
||||||
D3DRECT* rects = new D3DRECT[mRegionToClear.GetNumRects()];
|
|
||||||
nsIntRegionRectIterator iter(mRegionToClear);
|
|
||||||
const nsIntRect *r;
|
|
||||||
size_t i = 0;
|
|
||||||
while ((r = iter.Next())) {
|
|
||||||
rects[i].x1 = r->x;
|
|
||||||
rects[i].y1 = r->y;
|
|
||||||
rects[i].x2 = r->x + r->width;
|
|
||||||
rects[i].y2 = r->y + r->height;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
device()->Clear(i, rects, D3DCLEAR_TARGET,
|
|
||||||
0x00000000, 0, 0);
|
|
||||||
|
|
||||||
delete [] rects;
|
|
||||||
}
|
|
||||||
|
|
||||||
device()->EndScene();
|
device()->EndScene();
|
||||||
|
|
||||||
if (!mTarget) {
|
if (!mTarget) {
|
||||||
|
|
|
@ -219,6 +219,8 @@ public:
|
||||||
virtual bool AllocateForSurface(gfx::IntSize aSize,
|
virtual bool AllocateForSurface(gfx::IntSize aSize,
|
||||||
TextureAllocationFlags aFlags = ALLOC_DEFAULT) MOZ_OVERRIDE;
|
TextureAllocationFlags aFlags = ALLOC_DEFAULT) MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return true; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RefPtr<IDirect3DTexture9> mTexture;
|
RefPtr<IDirect3DTexture9> mTexture;
|
||||||
nsRefPtr<IDirect3DSurface9> mD3D9Surface;
|
nsRefPtr<IDirect3DSurface9> mD3D9Surface;
|
||||||
|
@ -271,6 +273,8 @@ public:
|
||||||
virtual bool AllocateForSurface(gfx::IntSize aSize,
|
virtual bool AllocateForSurface(gfx::IntSize aSize,
|
||||||
TextureAllocationFlags aFlags = ALLOC_DEFAULT) MOZ_OVERRIDE;
|
TextureAllocationFlags aFlags = ALLOC_DEFAULT) MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return true; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
nsRefPtr<gfxWindowsSurface> mSurface;
|
nsRefPtr<gfxWindowsSurface> mSurface;
|
||||||
RefPtr<gfx::DrawTarget> mDrawTarget;
|
RefPtr<gfx::DrawTarget> mDrawTarget;
|
||||||
|
@ -353,6 +357,8 @@ public:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return true; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TextureHostD3D9(TextureFlags aFlags);
|
TextureHostD3D9(TextureFlags aFlags);
|
||||||
IDirect3DDevice9* GetDevice();
|
IDirect3DDevice9* GetDevice();
|
||||||
|
|
|
@ -28,7 +28,7 @@ class SurfaceDescriptor;
|
||||||
class SurfaceDescriptorTiles;
|
class SurfaceDescriptorTiles;
|
||||||
class ThebesBufferData;
|
class ThebesBufferData;
|
||||||
class DeprecatedTextureClient;
|
class DeprecatedTextureClient;
|
||||||
class BasicTiledLayerBuffer;
|
class ClientTiledLayerBuffer;
|
||||||
class PTextureChild;
|
class PTextureChild;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -49,7 +49,6 @@ public:
|
||||||
|
|
||||||
CompositableForwarder()
|
CompositableForwarder()
|
||||||
: mSerial(++sSerialCounter)
|
: mSerial(++sSerialCounter)
|
||||||
, mMultiProcess(false)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -92,7 +91,11 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual void DestroyThebesBuffer(CompositableClient* aCompositable) = 0;
|
virtual void DestroyThebesBuffer(CompositableClient* aCompositable) = 0;
|
||||||
|
|
||||||
virtual void PaintedTiledLayerBuffer(CompositableClient* aCompositable,
|
/**
|
||||||
|
* Tell the CompositableHost on the compositor side what TiledLayerBuffer to
|
||||||
|
* use for the next composition.
|
||||||
|
*/
|
||||||
|
virtual void UseTiledLayerBuffer(CompositableClient* aCompositable,
|
||||||
const SurfaceDescriptorTiles& aTiledDescriptor) = 0;
|
const SurfaceDescriptorTiles& aTiledDescriptor) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -222,7 +225,7 @@ public:
|
||||||
* We only don't allow changing the backend type at runtime so this value can
|
* We only don't allow changing the backend type at runtime so this value can
|
||||||
* be queried once and will not change until Gecko is restarted.
|
* be queried once and will not change until Gecko is restarted.
|
||||||
*/
|
*/
|
||||||
LayersBackend GetCompositorBackendType() const
|
virtual LayersBackend GetCompositorBackendType() const MOZ_OVERRIDE
|
||||||
{
|
{
|
||||||
return mTextureFactoryIdentifier.mParentBackend;
|
return mTextureFactoryIdentifier.mParentBackend;
|
||||||
}
|
}
|
||||||
|
@ -237,11 +240,6 @@ public:
|
||||||
return mTextureFactoryIdentifier.mSupportsPartialUploads;
|
return mTextureFactoryIdentifier.mSupportsPartialUploads;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ForwardsToDifferentProcess() const
|
|
||||||
{
|
|
||||||
return mMultiProcess;
|
|
||||||
}
|
|
||||||
|
|
||||||
const TextureFactoryIdentifier& GetTextureFactoryIdentifier() const
|
const TextureFactoryIdentifier& GetTextureFactoryIdentifier() const
|
||||||
{
|
{
|
||||||
return mTextureFactoryIdentifier;
|
return mTextureFactoryIdentifier;
|
||||||
|
@ -254,7 +252,6 @@ protected:
|
||||||
nsTArray<RefPtr<TextureClient> > mTexturesToRemove;
|
nsTArray<RefPtr<TextureClient> > mTexturesToRemove;
|
||||||
const int32_t mSerial;
|
const int32_t mSerial;
|
||||||
static mozilla::Atomic<int32_t> sSerialCounter;
|
static mozilla::Atomic<int32_t> sSerialCounter;
|
||||||
bool mMultiProcess;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace layers {
|
namespace layers {
|
||||||
|
|
||||||
class BasicTiledLayerBuffer;
|
class ClientTiledLayerBuffer;
|
||||||
class Compositor;
|
class Compositor;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -224,9 +224,9 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation
|
||||||
compositable->SetPictureRect(op.picture());
|
compositable->SetPictureRect(op.picture());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CompositableOperation::TOpPaintTiledLayerBuffer: {
|
case CompositableOperation::TOpUseTiledLayerBuffer: {
|
||||||
MOZ_LAYERS_LOG(("[ParentSide] Paint TiledLayerBuffer"));
|
MOZ_LAYERS_LOG(("[ParentSide] Paint TiledLayerBuffer"));
|
||||||
const OpPaintTiledLayerBuffer& op = aEdit.get_OpPaintTiledLayerBuffer();
|
const OpUseTiledLayerBuffer& op = aEdit.get_OpUseTiledLayerBuffer();
|
||||||
CompositableParent* compositableParent = static_cast<CompositableParent*>(op.compositableParent());
|
CompositableParent* compositableParent = static_cast<CompositableParent*>(op.compositableParent());
|
||||||
CompositableHost* compositable =
|
CompositableHost* compositable =
|
||||||
compositableParent->GetCompositableHost();
|
compositableParent->GetCompositableHost();
|
||||||
|
@ -235,7 +235,7 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation
|
||||||
NS_ASSERTION(tileComposer, "compositable is not a tile composer");
|
NS_ASSERTION(tileComposer, "compositable is not a tile composer");
|
||||||
|
|
||||||
const SurfaceDescriptorTiles& tileDesc = op.tileLayerDescriptor();
|
const SurfaceDescriptorTiles& tileDesc = op.tileLayerDescriptor();
|
||||||
tileComposer->PaintedTiledLayerBuffer(this, tileDesc);
|
tileComposer->UseTiledLayerBuffer(this, tileDesc);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case CompositableOperation::TOpRemoveTexture: {
|
case CompositableOperation::TOpRemoveTexture: {
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "mozilla/RefPtr.h"
|
#include "mozilla/RefPtr.h"
|
||||||
#include "nsIMemoryReporter.h" // for nsIMemoryReporter
|
#include "nsIMemoryReporter.h" // for nsIMemoryReporter
|
||||||
#include "mozilla/Atomics.h" // for Atomic
|
#include "mozilla/Atomics.h" // for Atomic
|
||||||
|
#include "LayersTypes.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FIXME [bjacob] *** PURE CRAZYNESS WARNING ***
|
* FIXME [bjacob] *** PURE CRAZYNESS WARNING ***
|
||||||
|
@ -79,6 +80,16 @@ public:
|
||||||
MOZ_DECLARE_REFCOUNTED_TYPENAME(ISurfaceAllocator)
|
MOZ_DECLARE_REFCOUNTED_TYPENAME(ISurfaceAllocator)
|
||||||
ISurfaceAllocator() {}
|
ISurfaceAllocator() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the type of backend that is used off the main thread.
|
||||||
|
* We only don't allow changing the backend type at runtime so this value can
|
||||||
|
* be queried once and will not change until Gecko is restarted.
|
||||||
|
*
|
||||||
|
* XXX - With e10s this may not be true anymore. we can have accelerated widgets
|
||||||
|
* and non-accelerated widgets (small popups, etc.)
|
||||||
|
*/
|
||||||
|
virtual LayersBackend GetCompositorBackendType() const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocate shared memory that can be accessed by only one process at a time.
|
* Allocate shared memory that can be accessed by only one process at a time.
|
||||||
* Ownership of this memory is passed when the memory is sent in an IPDL
|
* Ownership of this memory is passed when the memory is sent in an IPDL
|
||||||
|
|
|
@ -32,7 +32,7 @@ class Shmem;
|
||||||
|
|
||||||
namespace layers {
|
namespace layers {
|
||||||
|
|
||||||
class BasicTiledLayerBuffer;
|
class ClientTiledLayerBuffer;
|
||||||
class ImageClient;
|
class ImageClient;
|
||||||
class ImageContainer;
|
class ImageContainer;
|
||||||
class ImageBridgeParent;
|
class ImageBridgeParent;
|
||||||
|
@ -280,7 +280,7 @@ public:
|
||||||
|
|
||||||
virtual void RemoveTexture(TextureClient* aTexture) MOZ_OVERRIDE;
|
virtual void RemoveTexture(TextureClient* aTexture) MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual void PaintedTiledLayerBuffer(CompositableClient* aCompositable,
|
virtual void UseTiledLayerBuffer(CompositableClient* aCompositable,
|
||||||
const SurfaceDescriptorTiles& aTileLayerDescriptor) MOZ_OVERRIDE
|
const SurfaceDescriptorTiles& aTileLayerDescriptor) MOZ_OVERRIDE
|
||||||
{
|
{
|
||||||
NS_RUNTIMEABORT("should not be called");
|
NS_RUNTIMEABORT("should not be called");
|
||||||
|
|
|
@ -58,6 +58,12 @@ ImageBridgeParent::~ImageBridgeParent()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LayersBackend
|
||||||
|
ImageBridgeParent::GetCompositorBackendType() const
|
||||||
|
{
|
||||||
|
return Compositor::GetBackend();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ImageBridgeParent::ActorDestroy(ActorDestroyReason aWhy)
|
ImageBridgeParent::ActorDestroy(ActorDestroyReason aWhy)
|
||||||
{
|
{
|
||||||
|
|
|
@ -42,6 +42,8 @@ public:
|
||||||
ImageBridgeParent(MessageLoop* aLoop, Transport* aTransport);
|
ImageBridgeParent(MessageLoop* aLoop, Transport* aTransport);
|
||||||
~ImageBridgeParent();
|
~ImageBridgeParent();
|
||||||
|
|
||||||
|
virtual LayersBackend GetCompositorBackendType() const MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
|
virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
|
||||||
|
|
||||||
static PImageBridgeParent*
|
static PImageBridgeParent*
|
||||||
|
|
|
@ -174,6 +174,12 @@ LayerTransactionParent::Destroy()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LayersBackend
|
||||||
|
LayerTransactionParent::GetCompositorBackendType() const
|
||||||
|
{
|
||||||
|
return mLayerManager->GetBackendType();
|
||||||
|
}
|
||||||
|
|
||||||
/* virtual */
|
/* virtual */
|
||||||
bool
|
bool
|
||||||
LayerTransactionParent::RecvUpdateNoSwap(const InfallibleTArray<Edit>& cset,
|
LayerTransactionParent::RecvUpdateNoSwap(const InfallibleTArray<Edit>& cset,
|
||||||
|
|
|
@ -75,6 +75,8 @@ public:
|
||||||
PLayerTransactionParent::DeallocShmem(aShmem);
|
PLayerTransactionParent::DeallocShmem(aShmem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual LayersBackend GetCompositorBackendType() const MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual bool IsSameProcess() const MOZ_OVERRIDE;
|
virtual bool IsSameProcess() const MOZ_OVERRIDE;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -255,8 +255,34 @@ struct OpRaiseToTopChild { PLayer container; PLayer childLayer; };
|
||||||
|
|
||||||
struct OpSetDiagnosticTypes { DiagnosticTypes diagnostics; };
|
struct OpSetDiagnosticTypes { DiagnosticTypes diagnostics; };
|
||||||
|
|
||||||
// Paint (buffer update)
|
union TileLock {
|
||||||
struct OpPaintTiledLayerBuffer {
|
Shmem;
|
||||||
|
uintptr_t;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TexturedTileDescriptor {
|
||||||
|
PTexture texture;
|
||||||
|
TileLock sharedLock;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PlaceholderTileDescriptor {
|
||||||
|
};
|
||||||
|
|
||||||
|
union TileDescriptor {
|
||||||
|
TexturedTileDescriptor;
|
||||||
|
PlaceholderTileDescriptor;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SurfaceDescriptorTiles {
|
||||||
|
nsIntRegion validRegion;
|
||||||
|
nsIntRegion paintedRegion;
|
||||||
|
TileDescriptor[] tiles;
|
||||||
|
int retainedWidth;
|
||||||
|
int retainedHeight;
|
||||||
|
float resolution;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OpUseTiledLayerBuffer {
|
||||||
PCompositable compositable;
|
PCompositable compositable;
|
||||||
SurfaceDescriptorTiles tileLayerDescriptor;
|
SurfaceDescriptorTiles tileLayerDescriptor;
|
||||||
};
|
};
|
||||||
|
@ -349,7 +375,7 @@ union CompositableOperation {
|
||||||
OpPaintTextureRegion;
|
OpPaintTextureRegion;
|
||||||
OpPaintTextureIncremental;
|
OpPaintTextureIncremental;
|
||||||
|
|
||||||
OpPaintTiledLayerBuffer;
|
OpUseTiledLayerBuffer;
|
||||||
|
|
||||||
OpRemoveTexture;
|
OpRemoveTexture;
|
||||||
|
|
||||||
|
|
|
@ -56,32 +56,6 @@ struct SharedTextureDescriptor {
|
||||||
bool inverted;
|
bool inverted;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BasicShmTileDescriptor {
|
|
||||||
Shmem reusableSurface;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct BasicTileDescriptor {
|
|
||||||
uintptr_t reusableSurface;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PlaceholderTileDescriptor {
|
|
||||||
};
|
|
||||||
|
|
||||||
union TileDescriptor {
|
|
||||||
BasicTileDescriptor;
|
|
||||||
BasicShmTileDescriptor;
|
|
||||||
PlaceholderTileDescriptor;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SurfaceDescriptorTiles {
|
|
||||||
nsIntRegion validRegion;
|
|
||||||
nsIntRegion paintedRegion;
|
|
||||||
TileDescriptor[] tiles;
|
|
||||||
int retainedWidth;
|
|
||||||
int retainedHeight;
|
|
||||||
float resolution;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct NewSurfaceDescriptorGralloc {
|
struct NewSurfaceDescriptorGralloc {
|
||||||
PGrallocBuffer buffer;
|
PGrallocBuffer buffer;
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -49,7 +49,7 @@ class Shmem;
|
||||||
|
|
||||||
namespace layers {
|
namespace layers {
|
||||||
|
|
||||||
class BasicTiledLayerBuffer;
|
class ClientTiledLayerBuffer;
|
||||||
|
|
||||||
typedef nsTArray<SurfaceDescriptor> BufferArray;
|
typedef nsTArray<SurfaceDescriptor> BufferArray;
|
||||||
typedef std::vector<Edit> EditVector;
|
typedef std::vector<Edit> EditVector;
|
||||||
|
@ -177,7 +177,6 @@ void
|
||||||
CompositableForwarder::IdentifyTextureHost(const TextureFactoryIdentifier& aIdentifier)
|
CompositableForwarder::IdentifyTextureHost(const TextureFactoryIdentifier& aIdentifier)
|
||||||
{
|
{
|
||||||
mTextureFactoryIdentifier = aIdentifier;
|
mTextureFactoryIdentifier = aIdentifier;
|
||||||
mMultiProcess = aIdentifier.mParentProcessId != XRE_GetProcessType();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ShadowLayerForwarder::ShadowLayerForwarder()
|
ShadowLayerForwarder::ShadowLayerForwarder()
|
||||||
|
@ -327,10 +326,10 @@ ShadowLayerForwarder::CheckSurfaceDescriptor(const SurfaceDescriptor* aDescripto
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
ShadowLayerForwarder::PaintedTiledLayerBuffer(CompositableClient* aCompositable,
|
ShadowLayerForwarder::UseTiledLayerBuffer(CompositableClient* aCompositable,
|
||||||
const SurfaceDescriptorTiles& aTileLayerDescriptor)
|
const SurfaceDescriptorTiles& aTileLayerDescriptor)
|
||||||
{
|
{
|
||||||
mTxn->AddNoSwapPaint(OpPaintTiledLayerBuffer(nullptr, aCompositable->GetIPDLActor(),
|
mTxn->AddNoSwapPaint(OpUseTiledLayerBuffer(nullptr, aCompositable->GetIPDLActor(),
|
||||||
aTileLayerDescriptor));
|
aTileLayerDescriptor));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ class gfxASurface;
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace layers {
|
namespace layers {
|
||||||
|
|
||||||
class BasicTiledLayerBuffer;
|
class ClientTiledLayerBuffer;
|
||||||
class CanvasClient;
|
class CanvasClient;
|
||||||
class CanvasLayerComposite;
|
class CanvasLayerComposite;
|
||||||
class CanvasSurface;
|
class CanvasSurface;
|
||||||
|
@ -255,13 +255,9 @@ public:
|
||||||
ShadowableLayer* aMaskLayer);
|
ShadowableLayer* aMaskLayer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify the compositor that a tiled layer buffer has changed
|
* See CompositableForwarder::UseTiledLayerBuffer
|
||||||
* that needs to be synced to the shadow retained copy. The tiled
|
|
||||||
* layer buffer will operate directly on the shadow retained buffer
|
|
||||||
* and is free to choose it's own internal representation (double buffering,
|
|
||||||
* copy on write, tiling).
|
|
||||||
*/
|
*/
|
||||||
virtual void PaintedTiledLayerBuffer(CompositableClient* aCompositable,
|
virtual void UseTiledLayerBuffer(CompositableClient* aCompositable,
|
||||||
const SurfaceDescriptorTiles& aTileLayerDescriptor) MOZ_OVERRIDE;
|
const SurfaceDescriptorTiles& aTileLayerDescriptor) MOZ_OVERRIDE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -106,6 +106,7 @@ EXPORTS.mozilla.layers += [
|
||||||
'client/ContentClient.h',
|
'client/ContentClient.h',
|
||||||
'client/ImageClient.h',
|
'client/ImageClient.h',
|
||||||
'client/TextureClient.h',
|
'client/TextureClient.h',
|
||||||
|
'client/TextureClientPool.h',
|
||||||
'client/TiledContentClient.h',
|
'client/TiledContentClient.h',
|
||||||
'composite/APZCTreeManager.h',
|
'composite/APZCTreeManager.h',
|
||||||
'composite/AsyncCompositionManager.h',
|
'composite/AsyncCompositionManager.h',
|
||||||
|
@ -234,6 +235,7 @@ UNIFIED_SOURCES += [
|
||||||
'client/ContentClient.cpp',
|
'client/ContentClient.cpp',
|
||||||
'client/ImageClient.cpp',
|
'client/ImageClient.cpp',
|
||||||
'client/TextureClient.cpp',
|
'client/TextureClient.cpp',
|
||||||
|
'client/TextureClientPool.cpp',
|
||||||
'client/TiledContentClient.cpp',
|
'client/TiledContentClient.cpp',
|
||||||
'composite/APZCTreeManager.cpp',
|
'composite/APZCTreeManager.cpp',
|
||||||
'composite/AsyncCompositionManager.cpp',
|
'composite/AsyncCompositionManager.cpp',
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
#if MOZ_ANDROID_OMTC
|
#if MOZ_ANDROID_OMTC
|
||||||
#include "TexturePoolOGL.h"
|
#include "TexturePoolOGL.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "GeckoProfiler.h"
|
#include "GeckoProfiler.h"
|
||||||
|
|
||||||
#define BUFFER_OFFSET(i) ((char *)nullptr + (i))
|
#define BUFFER_OFFSET(i) ((char *)nullptr + (i))
|
||||||
|
@ -136,6 +137,72 @@ DrawQuads(GLContext *aGLContext,
|
||||||
aGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
|
aGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MOZ_WIDGET_GONK
|
||||||
|
CompositorOGLGonkBackendSpecificData::CompositorOGLGonkBackendSpecificData(CompositorOGL* aCompositor)
|
||||||
|
: mCompositor(aCompositor)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
CompositorOGLGonkBackendSpecificData::~CompositorOGLGonkBackendSpecificData()
|
||||||
|
{
|
||||||
|
// Delete all textures by calling EndFrame twice
|
||||||
|
gl()->MakeCurrent();
|
||||||
|
EndFrame();
|
||||||
|
EndFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
GLContext*
|
||||||
|
CompositorOGLGonkBackendSpecificData::gl() const
|
||||||
|
{
|
||||||
|
return mCompositor->gl();
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint
|
||||||
|
CompositorOGLGonkBackendSpecificData::GetTexture()
|
||||||
|
{
|
||||||
|
GLuint texture = 0;
|
||||||
|
|
||||||
|
if (!mUnusedTextures.IsEmpty()) {
|
||||||
|
// Try to reuse one from the unused pile first
|
||||||
|
texture = mUnusedTextures[0];
|
||||||
|
mUnusedTextures.RemoveElementAt(0);
|
||||||
|
} else if (gl()->MakeCurrent()) {
|
||||||
|
// There isn't one to reuse, create one.
|
||||||
|
gl()->fGenTextures(1, &texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (texture) {
|
||||||
|
mCreatedTextures.AppendElement(texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CompositorOGLGonkBackendSpecificData::EndFrame()
|
||||||
|
{
|
||||||
|
gl()->MakeCurrent();
|
||||||
|
|
||||||
|
// Some platforms have issues unlocking Gralloc buffers even when they're
|
||||||
|
// rebound.
|
||||||
|
if (gfxPrefs::OverzealousGrallocUnlocking()) {
|
||||||
|
mUnusedTextures.AppendElements(mCreatedTextures);
|
||||||
|
mCreatedTextures.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete unused textures
|
||||||
|
for (size_t i = 0; i < mUnusedTextures.Length(); i++) {
|
||||||
|
GLuint texture = mUnusedTextures[i];
|
||||||
|
gl()->fDeleteTextures(1, &texture);
|
||||||
|
}
|
||||||
|
mUnusedTextures.Clear();
|
||||||
|
|
||||||
|
// Move all created textures into the unused pile
|
||||||
|
mUnusedTextures.AppendElements(mCreatedTextures);
|
||||||
|
mCreatedTextures.Clear();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
CompositorOGL::CompositorOGL(nsIWidget *aWidget, int aSurfaceWidth,
|
CompositorOGL::CompositorOGL(nsIWidget *aWidget, int aSurfaceWidth,
|
||||||
int aSurfaceHeight, bool aUseExternalSurfaceSize)
|
int aSurfaceHeight, bool aUseExternalSurfaceSize)
|
||||||
: mWidget(aWidget)
|
: mWidget(aWidget)
|
||||||
|
@ -1299,6 +1366,12 @@ CompositorOGL::EndFrame()
|
||||||
|
|
||||||
mCurrentRenderTarget = nullptr;
|
mCurrentRenderTarget = nullptr;
|
||||||
|
|
||||||
|
#ifdef MOZ_WIDGET_GONK
|
||||||
|
if (mCompositorBackendSpecificData) {
|
||||||
|
static_cast<CompositorOGLGonkBackendSpecificData*>(mCompositorBackendSpecificData.get())->EndFrame();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
mGLContext->SwapBuffers();
|
mGLContext->SwapBuffers();
|
||||||
mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
|
mGLContext->fBindBuffer(LOCAL_GL_ARRAY_BUFFER, 0);
|
||||||
}
|
}
|
||||||
|
@ -1407,6 +1480,17 @@ CompositorOGL::Resume()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MOZ_WIDGET_GONK
|
||||||
|
CompositorBackendSpecificData*
|
||||||
|
CompositorOGL::GetCompositorBackendSpecificData()
|
||||||
|
{
|
||||||
|
if (!mCompositorBackendSpecificData) {
|
||||||
|
mCompositorBackendSpecificData = new CompositorOGLGonkBackendSpecificData(this);
|
||||||
|
}
|
||||||
|
return mCompositorBackendSpecificData;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
TemporaryRef<DataTextureSource>
|
TemporaryRef<DataTextureSource>
|
||||||
CompositorOGL::CreateDataTextureSource(TextureFlags aFlags)
|
CompositorOGL::CreateDataTextureSource(TextureFlags aFlags)
|
||||||
{
|
{
|
||||||
|
|
|
@ -31,6 +31,9 @@
|
||||||
#include "nsXULAppAPI.h" // for XRE_GetProcessType
|
#include "nsXULAppAPI.h" // for XRE_GetProcessType
|
||||||
#include "nscore.h" // for NS_IMETHOD
|
#include "nscore.h" // for NS_IMETHOD
|
||||||
#include "VBOArena.h" // for gl::VBOArena
|
#include "VBOArena.h" // for gl::VBOArena
|
||||||
|
#ifdef MOZ_WIDGET_GONK
|
||||||
|
#include <ui/GraphicBuffer.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
class gfx3DMatrix;
|
class gfx3DMatrix;
|
||||||
class nsIWidget;
|
class nsIWidget;
|
||||||
|
@ -159,6 +162,10 @@ public:
|
||||||
|
|
||||||
virtual nsIWidget* GetWidget() const MOZ_OVERRIDE { return mWidget; }
|
virtual nsIWidget* GetWidget() const MOZ_OVERRIDE { return mWidget; }
|
||||||
|
|
||||||
|
#ifdef MOZ_WIDGET_GONK
|
||||||
|
virtual CompositorBackendSpecificData* GetCompositorBackendSpecificData() MOZ_OVERRIDE;
|
||||||
|
#endif
|
||||||
|
|
||||||
GLContext* gl() const { return mGLContext; }
|
GLContext* gl() const { return mGLContext; }
|
||||||
gfx::SurfaceFormat GetFBOFormat() const {
|
gfx::SurfaceFormat GetFBOFormat() const {
|
||||||
return gfx::SurfaceFormat::R8G8B8A8;
|
return gfx::SurfaceFormat::R8G8B8A8;
|
||||||
|
@ -313,8 +320,32 @@ private:
|
||||||
* FlipY for the y-flipping calculation.
|
* FlipY for the y-flipping calculation.
|
||||||
*/
|
*/
|
||||||
GLint mHeight;
|
GLint mHeight;
|
||||||
|
|
||||||
|
#ifdef MOZ_WIDGET_GONK
|
||||||
|
RefPtr<CompositorBackendSpecificData> mCompositorBackendSpecificData;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef MOZ_WIDGET_GONK
|
||||||
|
class CompositorOGLGonkBackendSpecificData : public CompositorBackendSpecificData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CompositorOGLGonkBackendSpecificData(CompositorOGL* aCompositor);
|
||||||
|
virtual ~CompositorOGLGonkBackendSpecificData();
|
||||||
|
|
||||||
|
GLuint GetTexture();
|
||||||
|
void EndFrame();
|
||||||
|
|
||||||
|
private:
|
||||||
|
gl::GLContext* gl() const;
|
||||||
|
|
||||||
|
RefPtr<CompositorOGL> mCompositor;
|
||||||
|
|
||||||
|
nsTArray<GLuint> mCreatedTextures;
|
||||||
|
nsTArray<GLuint> mUnusedTextures;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
|
|
||||||
#include "mozilla/gfx/2D.h"
|
#include "mozilla/gfx/2D.h"
|
||||||
#include "mozilla/layers/GrallocTextureClient.h"
|
#include "mozilla/layers/GrallocTextureClient.h"
|
||||||
#include "mozilla/layers/CompositableClient.h"
|
|
||||||
#include "mozilla/layers/CompositableForwarder.h"
|
#include "mozilla/layers/CompositableForwarder.h"
|
||||||
#include "mozilla/layers/ISurfaceAllocator.h"
|
#include "mozilla/layers/ISurfaceAllocator.h"
|
||||||
#include "mozilla/layers/ShadowLayerUtilsGralloc.h"
|
#include "mozilla/layers/ShadowLayerUtilsGralloc.h"
|
||||||
|
@ -95,28 +94,16 @@ GrallocTextureClientOGL::GrallocTextureClientOGL(GrallocBufferActor* aActor,
|
||||||
gfx::IntSize aSize,
|
gfx::IntSize aSize,
|
||||||
TextureFlags aFlags)
|
TextureFlags aFlags)
|
||||||
: BufferTextureClient(nullptr, gfx::SurfaceFormat::UNKNOWN, aFlags)
|
: BufferTextureClient(nullptr, gfx::SurfaceFormat::UNKNOWN, aFlags)
|
||||||
, mAllocator(nullptr)
|
|
||||||
, mMappedBuffer(nullptr)
|
, mMappedBuffer(nullptr)
|
||||||
{
|
{
|
||||||
InitWith(aActor, aSize);
|
InitWith(aActor, aSize);
|
||||||
MOZ_COUNT_CTOR(GrallocTextureClientOGL);
|
MOZ_COUNT_CTOR(GrallocTextureClientOGL);
|
||||||
}
|
}
|
||||||
|
|
||||||
GrallocTextureClientOGL::GrallocTextureClientOGL(CompositableClient* aCompositable,
|
|
||||||
gfx::SurfaceFormat aFormat,
|
|
||||||
TextureFlags aFlags)
|
|
||||||
: BufferTextureClient(aCompositable, aFormat, aFlags)
|
|
||||||
, mAllocator(nullptr)
|
|
||||||
, mMappedBuffer(nullptr)
|
|
||||||
{
|
|
||||||
MOZ_COUNT_CTOR(GrallocTextureClientOGL);
|
|
||||||
}
|
|
||||||
|
|
||||||
GrallocTextureClientOGL::GrallocTextureClientOGL(ISurfaceAllocator* aAllocator,
|
GrallocTextureClientOGL::GrallocTextureClientOGL(ISurfaceAllocator* aAllocator,
|
||||||
gfx::SurfaceFormat aFormat,
|
gfx::SurfaceFormat aFormat,
|
||||||
TextureFlags aFlags)
|
TextureFlags aFlags)
|
||||||
: BufferTextureClient(nullptr, aFormat, aFlags)
|
: BufferTextureClient(aAllocator, aFormat, aFlags)
|
||||||
, mAllocator(aAllocator)
|
|
||||||
, mMappedBuffer(nullptr)
|
, mMappedBuffer(nullptr)
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(GrallocTextureClientOGL);
|
MOZ_COUNT_CTOR(GrallocTextureClientOGL);
|
||||||
|
@ -457,15 +444,6 @@ GrallocTextureClientOGL::GetBufferSize() const
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ISurfaceAllocator*
|
|
||||||
GrallocTextureClientOGL::GetAllocator()
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mCompositable || mAllocator);
|
|
||||||
return mCompositable ?
|
|
||||||
mCompositable->GetForwarder() :
|
|
||||||
mAllocator;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namesapace layers
|
} // namesapace layers
|
||||||
} // namesapace mozilla
|
} // namesapace mozilla
|
||||||
|
|
||||||
|
|
|
@ -37,9 +37,6 @@ public:
|
||||||
GrallocTextureClientOGL(GrallocBufferActor* aActor,
|
GrallocTextureClientOGL(GrallocBufferActor* aActor,
|
||||||
gfx::IntSize aSize,
|
gfx::IntSize aSize,
|
||||||
TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT);
|
TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT);
|
||||||
GrallocTextureClientOGL(CompositableClient* aCompositable,
|
|
||||||
gfx::SurfaceFormat aFormat,
|
|
||||||
TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT);
|
|
||||||
GrallocTextureClientOGL(ISurfaceAllocator* aAllocator,
|
GrallocTextureClientOGL(ISurfaceAllocator* aAllocator,
|
||||||
gfx::SurfaceFormat aFormat,
|
gfx::SurfaceFormat aFormat,
|
||||||
TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT);
|
TextureFlags aFlags = TEXTURE_FLAGS_DEFAULT);
|
||||||
|
@ -52,6 +49,8 @@ public:
|
||||||
|
|
||||||
virtual bool ImplementsLocking() const MOZ_OVERRIDE { return true; }
|
virtual bool ImplementsLocking() const MOZ_OVERRIDE { return true; }
|
||||||
|
|
||||||
|
virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return false; }
|
||||||
|
|
||||||
virtual bool IsAllocated() const MOZ_OVERRIDE;
|
virtual bool IsAllocated() const MOZ_OVERRIDE;
|
||||||
|
|
||||||
virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) MOZ_OVERRIDE;
|
virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) MOZ_OVERRIDE;
|
||||||
|
@ -107,8 +106,6 @@ public:
|
||||||
void SetGraphicBufferLocked(GraphicBufferLocked* aBufferLocked);
|
void SetGraphicBufferLocked(GraphicBufferLocked* aBufferLocked);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ISurfaceAllocator* GetAllocator();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unfortunately, until bug 879681 is fixed we need to use a GrallocBufferActor.
|
* Unfortunately, until bug 879681 is fixed we need to use a GrallocBufferActor.
|
||||||
*/
|
*/
|
||||||
|
@ -118,8 +115,6 @@ protected:
|
||||||
|
|
||||||
android::sp<android::GraphicBuffer> mGraphicBuffer;
|
android::sp<android::GraphicBuffer> mGraphicBuffer;
|
||||||
|
|
||||||
RefPtr<ISurfaceAllocator> mAllocator;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Points to a mapped gralloc buffer between calls to lock and unlock.
|
* Points to a mapped gralloc buffer between calls to lock and unlock.
|
||||||
* Should be null outside of the lock-unlock pair.
|
* Should be null outside of the lock-unlock pair.
|
||||||
|
|
|
@ -104,7 +104,8 @@ GrallocTextureSourceOGL::~GrallocTextureSourceOGL()
|
||||||
mCompositor = nullptr;
|
mCompositor = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrallocTextureSourceOGL::BindTexture(GLenum aTextureUnit)
|
void
|
||||||
|
GrallocTextureSourceOGL::BindTexture(GLenum aTextureUnit)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* The job of this function is to ensure that the texture is tied to the
|
* The job of this function is to ensure that the texture is tied to the
|
||||||
|
@ -125,17 +126,46 @@ void GrallocTextureSourceOGL::BindTexture(GLenum aTextureUnit)
|
||||||
|
|
||||||
gl()->fActiveTexture(aTextureUnit);
|
gl()->fActiveTexture(aTextureUnit);
|
||||||
gl()->fBindTexture(textureTarget, tex);
|
gl()->fBindTexture(textureTarget, tex);
|
||||||
|
|
||||||
|
if (mCompositableBackendData) {
|
||||||
|
// There are two paths for locking/unlocking - if mCompositableBackendData is
|
||||||
|
// set, we use the texture on there, otherwise we use
|
||||||
|
// CompositorBackendSpecificData from the compositor and bind the EGLImage
|
||||||
|
// only in Lock().
|
||||||
if (!mEGLImage) {
|
if (!mEGLImage) {
|
||||||
mEGLImage = EGLImageCreateFromNativeBuffer(gl(), mGraphicBuffer->getNativeBuffer());
|
mEGLImage = EGLImageCreateFromNativeBuffer(gl(), mGraphicBuffer->getNativeBuffer());
|
||||||
}
|
}
|
||||||
gl()->fEGLImageTargetTexture2D(textureTarget, mEGLImage);
|
gl()->fEGLImageTargetTexture2D(textureTarget, mEGLImage);
|
||||||
|
}
|
||||||
|
|
||||||
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
|
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GrallocTextureSourceOGL::Lock()
|
||||||
|
{
|
||||||
|
if (mCompositableBackendData) return;
|
||||||
|
|
||||||
|
MOZ_ASSERT(IsValid());
|
||||||
|
|
||||||
|
CompositorOGLGonkBackendSpecificData* backendData =
|
||||||
|
static_cast<CompositorOGLGonkBackendSpecificData*>(mCompositor->GetCompositorBackendSpecificData());
|
||||||
|
mTexture = backendData->GetTexture();
|
||||||
|
|
||||||
|
GLuint textureTarget = GetTextureTarget();
|
||||||
|
|
||||||
|
gl()->MakeCurrent();
|
||||||
|
gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
|
||||||
|
gl()->fBindTexture(textureTarget, mTexture);
|
||||||
|
if (!mEGLImage) {
|
||||||
|
mEGLImage = EGLImageCreateFromNativeBuffer(gl(), mGraphicBuffer->getNativeBuffer());
|
||||||
|
}
|
||||||
|
gl()->fEGLImageTargetTexture2D(textureTarget, mEGLImage);
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
GrallocTextureSourceOGL::IsValid() const
|
GrallocTextureSourceOGL::IsValid() const
|
||||||
{
|
{
|
||||||
return !!gl() && !!mGraphicBuffer.get();
|
return !!gl() && !!mGraphicBuffer.get() && (!!mCompositor || !!mCompositableBackendData);
|
||||||
}
|
}
|
||||||
|
|
||||||
gl::GLContext*
|
gl::GLContext*
|
||||||
|
@ -178,7 +208,7 @@ GrallocTextureSourceOGL::GetFormat() const {
|
||||||
void
|
void
|
||||||
GrallocTextureSourceOGL::SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData)
|
GrallocTextureSourceOGL::SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData)
|
||||||
{
|
{
|
||||||
if (!aBackendData || !mGraphicBuffer.get()) {
|
if (!aBackendData) {
|
||||||
mCompositableBackendData = nullptr;
|
mCompositableBackendData = nullptr;
|
||||||
DeallocateDeviceData();
|
DeallocateDeviceData();
|
||||||
return;
|
return;
|
||||||
|
@ -285,7 +315,11 @@ GrallocTextureHostOGL::SetCompositor(Compositor* aCompositor)
|
||||||
bool
|
bool
|
||||||
GrallocTextureHostOGL::Lock()
|
GrallocTextureHostOGL::Lock()
|
||||||
{
|
{
|
||||||
return IsValid();
|
if (IsValid()) {
|
||||||
|
mTextureSource->Lock();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -384,10 +418,14 @@ GrallocTextureSourceOGL::GetAsSurface() {
|
||||||
GLuint
|
GLuint
|
||||||
GrallocTextureSourceOGL::GetGLTexture()
|
GrallocTextureSourceOGL::GetGLTexture()
|
||||||
{
|
{
|
||||||
|
if (mCompositableBackendData) {
|
||||||
mCompositableBackendData->SetCompositor(mCompositor);
|
mCompositableBackendData->SetCompositor(mCompositor);
|
||||||
return static_cast<CompositableDataGonkOGL*>(mCompositableBackendData.get())->GetTexture();
|
return static_cast<CompositableDataGonkOGL*>(mCompositableBackendData.get())->GetTexture();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return mTexture;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
GrallocTextureHostOGL::SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData)
|
GrallocTextureHostOGL::SetCompositableBackendSpecificData(CompositableBackendSpecificData* aBackendData)
|
||||||
{
|
{
|
||||||
|
|
|
@ -62,10 +62,13 @@ public:
|
||||||
|
|
||||||
GLuint GetGLTexture();
|
GLuint GetGLTexture();
|
||||||
|
|
||||||
|
void Lock();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
CompositorOGL* mCompositor;
|
CompositorOGL* mCompositor;
|
||||||
android::sp<android::GraphicBuffer> mGraphicBuffer;
|
android::sp<android::GraphicBuffer> mGraphicBuffer;
|
||||||
EGLImage mEGLImage;
|
EGLImage mEGLImage;
|
||||||
|
GLuint mTexture;
|
||||||
gfx::SurfaceFormat mFormat;
|
gfx::SurfaceFormat mFormat;
|
||||||
bool mNeedsReset;
|
bool mNeedsReset;
|
||||||
};
|
};
|
||||||
|
|
|
@ -36,6 +36,8 @@ public:
|
||||||
|
|
||||||
virtual TextureClientData* DropTextureData() MOZ_OVERRIDE;
|
virtual TextureClientData* DropTextureData() MOZ_OVERRIDE;
|
||||||
|
|
||||||
|
virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return false; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
RefPtr<MacIOSurface> mSurface;
|
RefPtr<MacIOSurface> mSurface;
|
||||||
bool mIsLocked;
|
bool mIsLocked;
|
||||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче