зеркало из https://github.com/mozilla/pjs.git
b=430873; avoid copy when doing canvas-canvas drawImage ops ; r+sr=roc,a=damon
This commit is contained in:
Родитель
47bc7d7c61
Коммит
bcc2c936d6
|
@ -50,6 +50,8 @@ class nsIFrame;
|
||||||
|
|
||||||
class nsIRenderingContext;
|
class nsIRenderingContext;
|
||||||
|
|
||||||
|
class nsICanvasRenderingContextInternal;
|
||||||
|
|
||||||
struct _cairo_surface;
|
struct _cairo_surface;
|
||||||
|
|
||||||
class nsICanvasElement : public nsISupports {
|
class nsICanvasElement : public nsISupports {
|
||||||
|
@ -92,6 +94,13 @@ public:
|
||||||
* is relative to the origin of the canvas frame.
|
* is relative to the origin of the canvas frame.
|
||||||
*/
|
*/
|
||||||
NS_IMETHOD InvalidateFrameSubrect (const nsRect& damageRect) = 0;
|
NS_IMETHOD InvalidateFrameSubrect (const nsRect& damageRect) = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the number of contexts in this canvas, and request a context at
|
||||||
|
* an index.
|
||||||
|
*/
|
||||||
|
virtual PRInt32 CountContexts () = 0;
|
||||||
|
virtual nsICanvasRenderingContextInternal *GetContextAtIndex (PRInt32 index) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsICanvasElement, NS_ICANVASELEMENT_IID)
|
NS_DEFINE_STATIC_IID_ACCESSOR(nsICanvasElement, NS_ICANVASELEMENT_IID)
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
{ 0xeab854fd, 0xaa5e, 0x44bb, { 0x8c, 0xc5, 0x8d, 0x02, 0xf8, 0x4b, 0x02, 0x16 } }
|
{ 0xeab854fd, 0xaa5e, 0x44bb, { 0x8c, 0xc5, 0x8d, 0x02, 0xf8, 0x4b, 0x02, 0x16 } }
|
||||||
|
|
||||||
class gfxContext;
|
class gfxContext;
|
||||||
|
class gfxASurface;
|
||||||
|
|
||||||
class nsICanvasRenderingContextInternal : public nsISupports {
|
class nsICanvasRenderingContextInternal : public nsISupports {
|
||||||
public:
|
public:
|
||||||
|
@ -72,6 +73,10 @@ public:
|
||||||
NS_IMETHOD GetInputStream(const char *aMimeType,
|
NS_IMETHOD GetInputStream(const char *aMimeType,
|
||||||
const PRUnichar *aEncoderOptions,
|
const PRUnichar *aEncoderOptions,
|
||||||
nsIInputStream **aStream) = 0;
|
nsIInputStream **aStream) = 0;
|
||||||
|
|
||||||
|
// If this canvas context can be represented with a simple Thebes surface,
|
||||||
|
// return the surface. Otherwise returns an error.
|
||||||
|
NS_IMETHOD GetThebesSurface(gfxASurface **surface) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsICanvasRenderingContextInternal,
|
NS_DEFINE_STATIC_IID_ACCESSOR(nsICanvasRenderingContextInternal,
|
||||||
|
|
|
@ -295,6 +295,7 @@ public:
|
||||||
NS_IMETHOD GetInputStream(const char* aMimeType,
|
NS_IMETHOD GetInputStream(const char* aMimeType,
|
||||||
const PRUnichar* aEncoderOptions,
|
const PRUnichar* aEncoderOptions,
|
||||||
nsIInputStream **aStream);
|
nsIInputStream **aStream);
|
||||||
|
NS_IMETHOD GetThebesSurface(gfxASurface **surface);
|
||||||
|
|
||||||
// nsISupports interface
|
// nsISupports interface
|
||||||
NS_DECL_ISUPPORTS
|
NS_DECL_ISUPPORTS
|
||||||
|
@ -411,8 +412,8 @@ protected:
|
||||||
|
|
||||||
// cairo helpers
|
// cairo helpers
|
||||||
nsresult CairoSurfaceFromElement(nsIDOMElement *imgElt,
|
nsresult CairoSurfaceFromElement(nsIDOMElement *imgElt,
|
||||||
|
PRBool forceCopy,
|
||||||
cairo_surface_t **aCairoSurface,
|
cairo_surface_t **aCairoSurface,
|
||||||
PRUint8 **imgDataOut,
|
|
||||||
PRInt32 *widthOut, PRInt32 *heightOut,
|
PRInt32 *widthOut, PRInt32 *heightOut,
|
||||||
nsIPrincipal **prinOut,
|
nsIPrincipal **prinOut,
|
||||||
PRBool *forceWriteOnlyOut);
|
PRBool *forceWriteOnlyOut);
|
||||||
|
@ -1089,12 +1090,11 @@ nsCanvasRenderingContext2D::CreatePattern(nsIDOMHTMLElement *image,
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_surface_t *imgSurf = nsnull;
|
cairo_surface_t *imgSurf = nsnull;
|
||||||
PRUint8 *imgData = nsnull;
|
|
||||||
PRInt32 imgWidth, imgHeight;
|
PRInt32 imgWidth, imgHeight;
|
||||||
nsCOMPtr<nsIPrincipal> principal;
|
nsCOMPtr<nsIPrincipal> principal;
|
||||||
PRBool forceWriteOnly = PR_FALSE;
|
PRBool forceWriteOnly = PR_FALSE;
|
||||||
rv = CairoSurfaceFromElement(image, &imgSurf, &imgData,
|
rv = CairoSurfaceFromElement(image, PR_TRUE,
|
||||||
&imgWidth, &imgHeight,
|
&imgSurf, &imgWidth, &imgHeight,
|
||||||
getter_AddRefs(principal), &forceWriteOnly);
|
getter_AddRefs(principal), &forceWriteOnly);
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
return rv;
|
return rv;
|
||||||
|
@ -1918,12 +1918,11 @@ nsCanvasRenderingContext2D::DrawImage()
|
||||||
cairo_matrix_t surfMat;
|
cairo_matrix_t surfMat;
|
||||||
cairo_pattern_t *pat;
|
cairo_pattern_t *pat;
|
||||||
cairo_path_t *old_path;
|
cairo_path_t *old_path;
|
||||||
PRUint8 *imgData = nsnull;
|
|
||||||
PRInt32 imgWidth, imgHeight;
|
PRInt32 imgWidth, imgHeight;
|
||||||
nsCOMPtr<nsIPrincipal> principal;
|
nsCOMPtr<nsIPrincipal> principal;
|
||||||
PRBool forceWriteOnly = PR_FALSE;
|
PRBool forceWriteOnly = PR_FALSE;
|
||||||
rv = CairoSurfaceFromElement(imgElt, &imgSurf, &imgData,
|
rv = CairoSurfaceFromElement(imgElt, PR_FALSE,
|
||||||
&imgWidth, &imgHeight,
|
&imgSurf, &imgWidth, &imgHeight,
|
||||||
getter_AddRefs(principal), &forceWriteOnly);
|
getter_AddRefs(principal), &forceWriteOnly);
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
return rv;
|
return rv;
|
||||||
|
@ -2154,12 +2153,15 @@ nsCanvasRenderingContext2D::ConvertJSValToXPCObject(nsISupports** aSupports, REF
|
||||||
/* cairo ARGB32 surfaces are ARGB stored as a packed 32-bit integer; on little-endian
|
/* cairo ARGB32 surfaces are ARGB stored as a packed 32-bit integer; on little-endian
|
||||||
* platforms, they appear as BGRA bytes in the surface data. The color values are also
|
* platforms, they appear as BGRA bytes in the surface data. The color values are also
|
||||||
* stored with premultiplied alpha.
|
* stored with premultiplied alpha.
|
||||||
|
*
|
||||||
|
* If forceCopy is FALSE, a surface may be returned that's only valid during the current
|
||||||
|
* operation. If it's TRUE, a copy will always be made that can safely be retained.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsCanvasRenderingContext2D::CairoSurfaceFromElement(nsIDOMElement *imgElt,
|
nsCanvasRenderingContext2D::CairoSurfaceFromElement(nsIDOMElement *imgElt,
|
||||||
|
PRBool forceCopy,
|
||||||
cairo_surface_t **aCairoSurface,
|
cairo_surface_t **aCairoSurface,
|
||||||
PRUint8 **imgData,
|
|
||||||
PRInt32 *widthOut,
|
PRInt32 *widthOut,
|
||||||
PRInt32 *heightOut,
|
PRInt32 *heightOut,
|
||||||
nsIPrincipal **prinOut,
|
nsIPrincipal **prinOut,
|
||||||
|
@ -2198,24 +2200,37 @@ nsCanvasRenderingContext2D::CairoSurfaceFromElement(nsIDOMElement *imgElt,
|
||||||
nsCOMPtr<nsICanvasElement> canvas = do_QueryInterface(imgElt);
|
nsCOMPtr<nsICanvasElement> canvas = do_QueryInterface(imgElt);
|
||||||
nsCOMPtr<nsINode> node = do_QueryInterface(imgElt);
|
nsCOMPtr<nsINode> node = do_QueryInterface(imgElt);
|
||||||
if (canvas && node) {
|
if (canvas && node) {
|
||||||
|
if (canvas->CountContexts() == 0)
|
||||||
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
|
|
||||||
PRUint32 w, h;
|
PRUint32 w, h;
|
||||||
rv = canvas->GetSize(&w, &h);
|
rv = canvas->GetSize(&w, &h);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
nsRefPtr<gfxImageSurface> surf =
|
nsRefPtr<gfxASurface> sourceSurface;
|
||||||
new gfxImageSurface (gfxIntSize(w, h), gfxASurface::ImageFormatARGB32);
|
|
||||||
|
if (!forceCopy && canvas->CountContexts() == 1) {
|
||||||
|
nsICanvasRenderingContextInternal *srcCanvas = canvas->GetContextAtIndex(0);
|
||||||
|
rv = srcCanvas->GetThebesSurface(getter_AddRefs(sourceSurface));
|
||||||
|
if (NS_FAILED(rv))
|
||||||
|
sourceSurface = nsnull;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sourceSurface == nsnull) {
|
||||||
|
nsRefPtr<gfxASurface> surf =
|
||||||
|
gfxPlatform::GetPlatform()->CreateOffscreenSurface
|
||||||
|
(gfxIntSize(w, h), gfxASurface::ImageFormatARGB32);
|
||||||
nsRefPtr<gfxContext> ctx = new gfxContext(surf);
|
nsRefPtr<gfxContext> ctx = new gfxContext(surf);
|
||||||
ctx->SetOperator(gfxContext::OPERATOR_CLEAR);
|
|
||||||
ctx->Paint();
|
|
||||||
ctx->SetOperator(gfxContext::OPERATOR_OVER);
|
ctx->SetOperator(gfxContext::OPERATOR_OVER);
|
||||||
|
|
||||||
rv = canvas->RenderContexts(ctx);
|
rv = canvas->RenderContexts(ctx);
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
return rv;
|
return rv;
|
||||||
|
sourceSurface = surf;
|
||||||
|
}
|
||||||
|
|
||||||
*aCairoSurface = surf->CairoSurface();
|
*aCairoSurface = sourceSurface->CairoSurface();
|
||||||
cairo_surface_reference(*aCairoSurface);
|
cairo_surface_reference(*aCairoSurface);
|
||||||
*imgData = surf->Data();
|
|
||||||
*widthOut = w;
|
*widthOut = w;
|
||||||
*heightOut = h;
|
*heightOut = h;
|
||||||
|
|
||||||
|
@ -2264,7 +2279,6 @@ nsCanvasRenderingContext2D::CairoSurfaceFromElement(nsIDOMElement *imgElt,
|
||||||
|
|
||||||
*aCairoSurface = gfxsurf->CairoSurface();
|
*aCairoSurface = gfxsurf->CairoSurface();
|
||||||
cairo_surface_reference (*aCairoSurface);
|
cairo_surface_reference (*aCairoSurface);
|
||||||
*imgData = nsnull;
|
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
@ -2647,3 +2661,18 @@ nsCanvasRenderingContext2D::PutImageData()
|
||||||
|
|
||||||
return Redraw();
|
return Redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsCanvasRenderingContext2D::GetThebesSurface(gfxASurface **surface)
|
||||||
|
{
|
||||||
|
if (!mThebesSurface) {
|
||||||
|
*surface = nsnull;
|
||||||
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*surface = mThebesSurface.get();
|
||||||
|
NS_ADDREF(*surface);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -93,6 +93,8 @@ public:
|
||||||
virtual void SetWriteOnly();
|
virtual void SetWriteOnly();
|
||||||
NS_IMETHOD InvalidateFrame ();
|
NS_IMETHOD InvalidateFrame ();
|
||||||
NS_IMETHOD InvalidateFrameSubrect (const nsRect& damageRect);
|
NS_IMETHOD InvalidateFrameSubrect (const nsRect& damageRect);
|
||||||
|
virtual PRInt32 CountContexts();
|
||||||
|
virtual nsICanvasRenderingContextInternal *GetContextAtIndex (PRInt32 index);
|
||||||
|
|
||||||
NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
|
NS_IMETHOD_(PRBool) IsAttributeMapped(const nsIAtom* aAttribute) const;
|
||||||
nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
|
nsMapRuleToAttributesFunc GetAttributeMappingFunction() const;
|
||||||
|
@ -553,3 +555,21 @@ nsHTMLCanvasElement::InvalidateFrameSubrect(const nsRect& damageRect)
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PRInt32
|
||||||
|
nsHTMLCanvasElement::CountContexts()
|
||||||
|
{
|
||||||
|
if (mCurrentContext)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsICanvasRenderingContextInternal *
|
||||||
|
nsHTMLCanvasElement::GetContextAtIndex (PRInt32 index)
|
||||||
|
{
|
||||||
|
if (mCurrentContext && index == 0)
|
||||||
|
return mCurrentContext.get();
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче