canvas3d fixes for bug 396972; npotb

This commit is contained in:
vladimir@pobox.com 2007-09-25 14:20:42 -07:00
parent aeb3ae3444
commit b36cf515a1
5 changed files with 86 additions and 642 deletions

View File

@ -52,39 +52,29 @@ EXPORT_LIBRARY = 0
IS_COMPONENT = 1
MODULE_NAME = nsCanvas3DModule
GRE_MODULE = 1
MOZILLA_INTERNAL_API = 1
BUILD_STATIC_LIBS =
REQUIRES = \
xpcom \
string \
gfx \
unicharutil \
xpconnect \
thebes \
cairo \
content \
dom \
caps \
js \
imglib2 \
necko \
gfx \
layout \
widget \
dom \
js \
locale \
unicharutil \
necko \
view \
pref \
docshell \
xpconnect \
xuldoc \
caps \
imglib2 \
mimetype \
exthandler \
uconv \
intl \
cairo \
view \
$(NULL)
ifdef MOZ_ENABLE_CAIRO_GFX
REQUIRES += thebes
endif
ifdef MOZ_X11
EXTRA_DSO_LIBS += GL
endif
@ -109,12 +99,7 @@ CPPSRCS = nsCanvas3DModule.cpp \
DEFINES += -DXPCOM_GLUE -DXPCOM_GLUE_USE_NSPR -DGLEW_MX -DGLEW_STATIC
EXTRA_DSO_LIBS += js3250 xpcom xpcom_core unicharutil_s
# mozcairo mozlibpixman
ifdef MOZ_ENABLE_CAIRO_GFX
EXTRA_DSO_LDOPTS += $(DEPTH)/gfx/thebes/src/thebes.lib $(DEPTH)/gfx/src/gkgfx.lib
endif
EXTRA_DSO_LIBS += js3250 xpcom xul
# Hack for getting an extension built against static vs. dynamic versions of firefox
##ifeq (,$(BUILD_STATIC_LIBS))
@ -138,4 +123,4 @@ endif
ifneq (,$(filter $(MOZ_WIDGET_TOOLKIT),mac cocoa))
endif
EXTRA_DSO_LDOPTS += $(LIBS_DIR) $(EXTRA_DSO_LIBS)
EXTRA_DSO_LDOPTS += $(LIBS_DIR) $(EXTRA_DSO_LIBS) $(XPCOM_GLUE_LDOPTS)

View File

@ -50,9 +50,7 @@
#include "nsIView.h"
#include "nsIViewManager.h"
#ifndef MOZILLA_1_8_BRANCH
#include "nsIDocument.h"
#endif
#include "nsTransform2D.h"
@ -68,20 +66,17 @@
#include "nsIImageLoadingContent.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIImage.h"
#include "nsIFrame.h"
#include "nsDOMError.h"
#include "nsIJSRuntimeService.h"
#ifndef MOZILLA_1_8_BRANCH
#include "nsIPrefService.h"
#include "nsIClassInfoImpl.h"
#endif
#include "nsServiceManagerUtils.h"
#include "nsDOMError.h"
#include "nsContentUtils.h"
#include "nsIXPConnect.h"
#include "jsapi.h"
@ -90,34 +85,8 @@
// we're hoping that something is setting us up the remap
#include "cairo.h"
#ifdef MOZ_CAIRO_GFX
#include "gfxContext.h"
#include "gfxASurface.h"
#endif
#ifdef XP_WIN
#ifdef MOZILLA_1_8_BRANCH
struct _cairo_surface_win32_hack {
void *ptr;
unsigned int refcnt;
cairo_status_t st;
cairo_bool_t finished;
/* array_t */
int sz;
int num_el;
int el_sz;
void *elements;
double dx, dy, dxs, dys;
unsigned int a;
unsigned int b;
/* win32 */
cairo_format_t format;
};
#endif
#endif
#ifdef MOZ_X11
#include <gdk/gdk.h>
@ -544,13 +513,8 @@ nsCanvasRenderingContextGLPrivate::SetDimensions(PRInt32 width, PRInt32 height)
return NS_OK;
}
/*
* This is identical to nsCanvasRenderingContext2D::Render, we just don't
* have a good place to put it; though maybe I want a CanvasContextImpl that
* all this stuff can derive from?
*/
NS_IMETHODIMP
nsCanvasRenderingContextGLPrivate::Render(nsIRenderingContext *rc)
nsCanvasRenderingContextGLPrivate::Render(gfxContext *ctx)
{
nsresult rv = NS_OK;
@ -560,8 +524,6 @@ nsCanvasRenderingContextGLPrivate::Render(nsIRenderingContext *rc)
if (!mGLPbuffer->ThebesSurface())
return NS_OK;
#ifdef MOZ_CAIRO_GFX
gfxContext* ctx = (gfxContext*) rc->GetNativeGraphicData(nsIRenderingContext::NATIVE_THEBES_CONTEXT);
nsRefPtr<gfxASurface> surf = mGLPbuffer->ThebesSurface();
nsRefPtr<gfxPattern> pat = new gfxPattern(surf);
@ -570,171 +532,13 @@ nsCanvasRenderingContextGLPrivate::Render(nsIRenderingContext *rc)
ctx->NewPath();
ctx->PixelSnappedRectangleAndSetPattern(gfxRect(0, 0, mWidth, mHeight), pat);
ctx->Fill();
#else
// non-Thebes; this becomes exciting
cairo_surface_t *dest = nsnull;
cairo_t *dest_cr = nsnull;
#ifdef XP_WIN
void *ptr = nsnull;
#ifdef MOZILLA_1_8_BRANCH
rv = rc->RetrieveCurrentNativeGraphicData(&ptr);
if (NS_FAILED(rv) || !ptr)
return NS_ERROR_FAILURE;
#else
ptr = rc->GetNativeGraphicData(nsIRenderingContext::NATIVE_WINDOWS_DC);
#endif
HDC dc = (HDC) ptr;
dest = cairo_win32_surface_create (dc);
dest_cr = cairo_create (dest);
#endif
#ifdef MOZ_WIDGET_GTK2
GdkDrawable *gdkdraw = nsnull;
#ifdef MOZILLA_1_8_BRANCH
rv = rc->RetrieveCurrentNativeGraphicData((void**) &gdkdraw);
if (NS_FAILED(rv) || !gdkdraw)
return NS_ERROR_FAILURE;
#else
gdkdraw = (GdkDrawable*) rc->GetNativeGraphicData(nsIRenderingContext::NATIVE_GDK_DRAWABLE);
if (!gdkdraw)
return NS_ERROR_FAILURE;
#endif
gint w, h;
gdk_drawable_get_size (gdkdraw, &w, &h);
dest = cairo_xlib_surface_create (GDK_DRAWABLE_XDISPLAY(gdkdraw),
GDK_DRAWABLE_XID(gdkdraw),
GDK_VISUAL_XVISUAL(gdk_drawable_get_visual(gdkdraw)),
w, h);
dest_cr = cairo_create (dest);
#endif
nsTransform2D *tx = nsnull;
rc->GetCurrentTransform(tx);
nsCOMPtr<nsIDeviceContext> dctx;
rc->GetDeviceContext(*getter_AddRefs(dctx));
// Until we can use the quartz2 surface, mac will be different,
// since we'll use CG to render.
#ifndef XP_MACOSX
float x0 = 0.0, y0 = 0.0;
float sx = 1.0, sy = 1.0;
if (tx->GetType() & MG_2DTRANSLATION) {
tx->Transform(&x0, &y0);
}
if (tx->GetType() & MG_2DSCALE) {
sx = sy = dctx->DevUnitsToTwips();
tx->TransformNoXLate(&sx, &sy);
}
cairo_translate (dest_cr, NSToIntRound(x0), NSToIntRound(y0));
if (sx != 1.0 || sy != 1.0)
cairo_scale (dest_cr, sx, sy);
cairo_rectangle (dest_cr, 0, 0, mWidth, mHeight);
cairo_clip (dest_cr);
cairo_set_source_surface (dest_cr, mCairoImageSurface, 0, 0);
cairo_paint (dest_cr);
if (dest_cr)
cairo_destroy (dest_cr);
if (dest)
cairo_surface_destroy (dest);
#else
// OSX path
CGrafPtr port = nsnull;
#ifdef MOZILLA_1_8_BRANCH
rv = rc->RetrieveCurrentNativeGraphicData((void**) &port);
if (NS_FAILED(rv) || !port)
return NS_ERROR_FAILURE;
#else
port = (CGrafPtr) rc->GetNativeGraphicData(nsIRenderingContext::NATIVE_MAC_THING);
if (!port)
return NS_ERROR_FAILURE;
#endif
struct Rect portRect;
GetPortBounds(port, &portRect);
CGContextRef cgc;
OSStatus status;
status = QDBeginCGContext (port, &cgc);
if (status != noErr)
return NS_ERROR_FAILURE;
CGDataProviderRef dataProvider;
CGImageRef img;
dataProvider = CGDataProviderCreateWithData (NULL, mImageBuffer,
mWidth * mHeight * 4,
NULL);
CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
img = CGImageCreate (mWidth, mHeight, 8, 32, mWidth * 4, rgb,
kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host,
dataProvider, NULL, false, kCGRenderingIntentDefault);
CGColorSpaceRelease (rgb);
CGDataProviderRelease (dataProvider);
float x0 = 0.0, y0 = 0.0;
float sx = 1.0, sy = 1.0;
if (tx->GetType() & MG_2DTRANSLATION) {
tx->Transform(&x0, &y0);
}
if (tx->GetType() & MG_2DSCALE) {
float p2t = dctx->DevUnitsToTwips();
sx = p2t, sy = p2t;
tx->TransformNoXLate(&sx, &sy);
}
/* Compensate for the bottom-left Y origin */
CGContextTranslateCTM (cgc, NSToIntRound(x0),
portRect.bottom - portRect.top - NSToIntRound(y0) - NSToIntRound(mHeight * sy));
if (sx != 1.0 || sy != 1.0)
CGContextScaleCTM (cgc, sx, sy);
CGContextDrawImage (cgc, CGRectMake(0, 0, mWidth, mHeight), img);
CGImageRelease (img);
status = QDEndCGContext (port, &cgc);
/* if EndCGContext fails, what can we do? */
#endif
#endif
return rv;
}
NS_IMETHODIMP
nsCanvasRenderingContextGLPrivate::RenderToSurface(cairo_surface_t *surf)
{
return NS_OK;
}
nsIFrame*
nsCanvasRenderingContextGLPrivate::GetCanvasLayoutFrame()
{
if (!mCanvasElement)
return nsnull;
nsIFrame *fr = nsnull;
mCanvasElement->GetPrimaryCanvasFrame(&fr);
return fr;
}
NS_IMETHODIMP
nsCanvasRenderingContextGLPrivate::GetInputStream(const nsACString& aMimeType,
const nsAString& aEncoderOptions,
nsCanvasRenderingContextGLPrivate::GetInputStream(const char* aMimeType,
const PRUnichar* aEncoderOptions,
nsIInputStream **aStream)
{
return NS_ERROR_NOT_IMPLEMENTED;
@ -746,7 +550,7 @@ nsCanvasRenderingContextGLPrivate::GetInputStream(const nsACString& aMimeType,
nsresult
nsCanvasRenderingContextGLPrivate::CairoSurfaceFromElement(nsIDOMElement *imgElt,
cairo_surface_t **aCairoSurface,
gfxASurface **aThebesSurface,
PRUint8 **imgData,
PRInt32 *widthOut, PRInt32 *heightOut,
nsIURI **uriOut, PRBool *forceWriteOnlyOut)
@ -781,23 +585,20 @@ nsCanvasRenderingContextGLPrivate::CairoSurfaceFromElement(nsIDOMElement *imgElt
rv = canvas->GetSize(&w, &h);
NS_ENSURE_SUCCESS(rv, rv);
PRUint8 *data = (PRUint8*) PR_Malloc(w * h * 4);
cairo_surface_t *surf =
cairo_image_surface_create_for_data (data, CAIRO_FORMAT_ARGB32,
w, h, w*4);
cairo_t *cr = cairo_create (surf);
cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
cairo_paint (cr);
cairo_destroy (cr);
nsRefPtr<gfxImageSurface> surf =
new gfxImageSurface (gfxIntSize(w, h), gfxASurface::ImageFormatARGB32);
nsRefPtr<gfxContext> ctx = new gfxContext(surf);
ctx->SetOperator(gfxContext::OPERATOR_CLEAR);
ctx->Paint();
ctx->SetOperator(gfxContext::OPERATOR_OVER);
rv = canvas->RenderContextsToSurface(surf);
if (NS_FAILED(rv)) {
cairo_surface_destroy (surf);
rv = canvas->RenderContexts(ctx);
if (NS_FAILED(rv))
return rv;
}
*aCairoSurface = surf;
*imgData = data;
NS_ADDREF(surf.get());
*aThebesSurface = surf;
*imgData = surf->Data();
*widthOut = w;
*heightOut = h;
@ -831,266 +632,10 @@ nsCanvasRenderingContextGLPrivate::CairoSurfaceFromElement(nsIDOMElement *imgElt
if (heightOut)
*heightOut = imgHeight;
#ifdef MOZ_CAIRO_GFX
gfxASurface* gfxsurf = nsnull;
rv = img->GetSurface(&gfxsurf);
rv = img->GetSurface(aThebesSurface);
NS_ENSURE_SUCCESS(rv, rv);
*aCairoSurface = gfxsurf->CairoSurface();
cairo_surface_reference (*aCairoSurface);
*imgData = nsnull;
#else
//
// We now need to create a cairo_surface with the same data as
// this image element.
//
PRUint8 *cairoImgData = (PRUint8 *)nsMemory::Alloc(imgHeight * imgWidth * 4);
PRUint8 *outData = cairoImgData;
gfx_format format;
rv = frame->GetFormat(&format);
NS_ENSURE_SUCCESS(rv, rv);
rv = frame->LockImageData();
if (img->GetHasAlphaMask())
rv |= frame->LockAlphaData();
if (NS_FAILED(rv)) {
nsMemory::Free(cairoImgData);
return NS_ERROR_FAILURE;
}
PRUint8 *inPixBits, *inAlphaBits = nsnull;
PRUint32 inPixStride, inAlphaStride = 0;
inPixBits = img->GetBits();
inPixStride = img->GetLineStride();
if (img->GetHasAlphaMask()) {
inAlphaBits = img->GetAlphaBits();
inAlphaStride = img->GetAlphaLineStride();
}
PRBool topToBottom = img->GetIsRowOrderTopToBottom();
PRBool useBGR;
// The gtk backend optimizes away the alpha mask of images
// with a fully opaque alpha, but doesn't update its format (bug?);
// you end up with a RGB_A8 image with GetHasAlphaMask() == false.
// We need to treat that case as RGB.
if ((format == gfxIFormats::RGB || format == gfxIFormats::BGR) ||
(!(img->GetHasAlphaMask()) && (format == gfxIFormats::RGB_A8 || format == gfxIFormats::BGR_A8)))
{
useBGR = (format & 1);
#ifdef IS_BIG_ENDIAN
useBGR = !useBGR;
#endif
for (PRUint32 j = 0; j < (PRUint32) imgHeight; j++) {
PRUint32 rowIndex;
if (topToBottom)
rowIndex = j;
else
rowIndex = imgHeight - j - 1;
PRUint8 *inrowrgb = inPixBits + (inPixStride * rowIndex);
for (PRUint32 i = 0; i < (PRUint32) imgWidth; i++) {
// handle rgb data; no alpha to premultiply
#ifdef XP_MACOSX
// skip extra OSX byte
inrowrgb++;
#endif
PRUint8 r, g, b;
if (useBGR) {
b = *inrowrgb++;
g = *inrowrgb++;
r = *inrowrgb++;
} else {
r = *inrowrgb++;
g = *inrowrgb++;
b = *inrowrgb++;
}
#ifdef IS_BIG_ENDIAN
// alpha
*outData++ = 0xff;
#endif
*outData++ = r;
*outData++ = g;
*outData++ = b;
#ifdef IS_LITTLE_ENDIAN
// alpha
*outData++ = 0xff;
#endif
}
}
rv = NS_OK;
} else if (format == gfxIFormats::RGB_A1 || format == gfxIFormats::BGR_A1) {
useBGR = (format & 1);
#ifdef IS_BIG_ENDIAN
useBGR = !useBGR;
#endif
for (PRUint32 j = 0; j < (PRUint32) imgHeight; j++) {
PRUint32 rowIndex;
if (topToBottom)
rowIndex = j;
else
rowIndex = imgHeight - j - 1;
PRUint8 *inrowrgb = inPixBits + (inPixStride * rowIndex);
PRUint8 *inrowalpha = inAlphaBits + (inAlphaStride * rowIndex);
for (PRUint32 i = 0; i < (PRUint32) imgWidth; i++) {
// pull out the bit value into alpha
PRInt32 bit = i % 8;
PRInt32 byte = i / 8;
#ifdef IS_LITTLE_ENDIAN
PRUint8 a = (inrowalpha[byte] >> (7-bit)) & 1;
#else
PRUint8 a = (inrowalpha[byte] >> bit) & 1;
#endif
#ifdef XP_MACOSX
// skip extra X8 byte on OSX
inrowrgb++;
#endif
// handle rgb data; need to multiply the alpha out,
// but we short-circuit that here since we know that a
// can only be 0 or 1
if (a) {
PRUint8 r, g, b;
if (useBGR) {
b = *inrowrgb++;
g = *inrowrgb++;
r = *inrowrgb++;
} else {
r = *inrowrgb++;
g = *inrowrgb++;
b = *inrowrgb++;
}
#ifdef IS_BIG_ENDIAN
// alpha
*outData++ = 0xff;
#endif
*outData++ = r;
*outData++ = g;
*outData++ = b;
#ifdef IS_LITTLE_ENDIAN
// alpha
*outData++ = 0xff;
#endif
} else {
// alpha is 0, so we need to write all 0's,
// ignoring input color
inrowrgb += 3;
*outData++ = 0;
*outData++ = 0;
*outData++ = 0;
*outData++ = 0;
}
}
}
rv = NS_OK;
} else if (format == gfxIFormats::RGB_A8 || format == gfxIFormats::BGR_A8) {
useBGR = (format & 1);
#ifdef IS_BIG_ENDIAN
useBGR = !useBGR;
#endif
for (PRUint32 j = 0; j < (PRUint32) imgHeight; j++) {
PRUint32 rowIndex;
if (topToBottom)
rowIndex = j;
else
rowIndex = imgHeight - j - 1;
PRUint8 *inrowrgb = inPixBits + (inPixStride * rowIndex);
PRUint8 *inrowalpha = inAlphaBits + (inAlphaStride * rowIndex);
for (PRUint32 i = 0; i < (PRUint32) imgWidth; i++) {
// pull out alpha; we'll need it to premultiply
PRUint8 a = *inrowalpha++;
// handle rgb data; we need to fully premultiply
// with the alpha
#ifdef XP_MACOSX
// skip extra X8 byte on OSX
inrowrgb++;
#endif
// XXX gcc bug: gcc seems to push "r" into a register
// early, and pretends that it's in that register
// throughout the 3 macros below. At the end
// of the 3rd macro, the correct r value is
// calculated but never stored anywhere -- the r variable
// has the value of the low byte of register that it
// was stuffed into, which has the result of some
// intermediate calculation.
// I've seen this on gcc 3.4.2 x86 (Fedora Core 3)
// and gcc 3.3 PPC (OS X 10.3)
//PRUint8 b, g, r;
//FAST_DIVIDE_BY_255(b, *inrowrgb++ * a - a / 2);
//FAST_DIVIDE_BY_255(g, *inrowrgb++ * a - a / 2);
//FAST_DIVIDE_BY_255(r, *inrowrgb++ * a - a / 2);
PRUint8 r, g, b;
if (useBGR) {
b = (*inrowrgb++ * a - a / 2) / 255;
g = (*inrowrgb++ * a - a / 2) / 255;
r = (*inrowrgb++ * a - a / 2) / 255;
} else {
r = (*inrowrgb++ * a - a / 2) / 255;
g = (*inrowrgb++ * a - a / 2) / 255;
b = (*inrowrgb++ * a - a / 2) / 255;
}
#ifdef IS_BIG_ENDIAN
*outData++ = a;
#endif
*outData++ = r;
*outData++ = g;
*outData++ = b;
#ifdef IS_LITTLE_ENDIAN
*outData++ = a;
#endif
}
}
rv = NS_OK;
} else {
rv = NS_ERROR_FAILURE;
}
if (img->GetHasAlphaMask())
frame->UnlockAlphaData();
frame->UnlockImageData();
if (NS_FAILED(rv)) {
nsMemory::Free(cairoImgData);
return rv;
}
cairo_surface_t *imgSurf =
cairo_image_surface_create_for_data(cairoImgData, CAIRO_FORMAT_ARGB32,
imgWidth, imgHeight, imgWidth*4);
*aCairoSurface = imgSurf;
*imgData = cairoImgData;
#endif
return NS_OK;
}
@ -1125,27 +670,6 @@ nsCanvasRenderingContextGLPrivate::DoDrawImageSecurityCheck(nsIURI* aURI, PRBool
}
fprintf (stderr, "DoDrawImageSecuritycheck this 5: %p\n", this);
#ifdef MOZILLA_1_8_BRANCH
#if 0
nsCOMPtr<nsIDOMNode> elem = do_QueryInterface(mCanvasElement);
if (elem && ssm) {
nsCOMPtr<nsIPrincipal> elemPrincipal;
nsCOMPtr<nsIPrincipal> uriPrincipal;
nsCOMPtr<nsIDocument> elemDocument;
nsContentUtils::GetDocumentAndPrincipal(elem, getter_AddRefs(elemDocument), getter_AddRefs(elemPrincipal));
ssm->GetCodebasePrincipal(aURI, getter_AddRefs(uriPrincipal));
if (uriPrincipal && elemPrincipal) {
nsresult rv =
ssm->CheckSameOriginPrincipal(elemPrincipal, uriPrincipal);
if (NS_SUCCEEDED(rv)) {
// Same origin
return;
}
}
}
#endif
#else
nsCOMPtr<nsINode> elem = do_QueryInterface(mCanvasElement);
if (elem && ssm) {
nsCOMPtr<nsIPrincipal> uriPrincipal;
@ -1160,7 +684,6 @@ nsCanvasRenderingContextGLPrivate::DoDrawImageSecurityCheck(nsIURI* aURI, PRBool
}
}
}
#endif
fprintf (stderr, "DoDrawImageSecuritycheck this 6: %p\n", this); fflush(stderr);
mCanvasElement->SetWriteOnly();
@ -1221,43 +744,11 @@ nsCanvasRenderingContextGLPrivate::DoSwapBuffers()
{
mGLPbuffer->SwapBuffers();
// then invalidate the region and do a sync redraw
// (uh, why sync?)
nsIFrame *frame = GetCanvasLayoutFrame();
if (frame) {
nsRect r = frame->GetRect();
r.x = r.y = 0;
// sync redraw
//frame->Invalidate(r, PR_TRUE);
// nsIFrame::Invalidate is an internal non-virtual method,
// so we basically recreate it here. I would suggest
// an InvalidateExternal for the trunk.
nsIPresShell *shell = frame->PresContext()->GetPresShell();
if (shell) {
PRBool suppressed = PR_FALSE;
shell->IsPaintingSuppressed(&suppressed);
if (suppressed)
return NS_OK;
}
// maybe VMREFRESH_IMMEDIATE in some cases,
// need to think
PRUint32 flags = NS_VMREFRESH_NO_SYNC;
if (frame->HasView()) {
nsIView* view = frame->GetViewExternal();
view->GetViewManager()->UpdateView(view, r, flags);
} else {
nsPoint offset;
nsIView *view;
frame->GetOffsetFromView(offset, &view);
NS_ASSERTION(view, "no view");
r += offset;
view->GetViewManager()->UpdateView(view, r, flags);
}
}
// then invalidate the region and do a redraw
if (!mCanvasElement)
return NS_OK;
mCanvasElement->InvalidateFrame();
return NS_OK;
}
@ -1298,3 +789,16 @@ nsCanvasRenderingContextGLPrivate::SafeToCreateCanvas3DContext()
return PR_FALSE;
}
/*
* We need this here, because nsAString has a different type name based on whether it's
* used internally or externally. BeginPrinting isn't ever called, but gfxImageSurface
* wants to inherit the default definition, and it can't find it. So instead, we just
* stick a stub here to shut the compiler up, because we never call this method.
*/
nsresult
gfxASurface::BeginPrinting(const nsAString& aTitle, const nsAString& aPrintToFileName)
{
return NS_ERROR_NOT_IMPLEMENTED;
}

View File

@ -44,6 +44,8 @@
#include <stdlib.h>
#include "prmem.h"
#include "nsStringGlue.h"
#include "nsICanvasRenderingContextGLBuffer.h"
#include "nsICanvasRenderingContextInternal.h"
#include "nsIDOMHTMLCanvasElement.h"
@ -64,7 +66,6 @@
#include "nsIImageLoadingContent.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIImage.h"
#include "nsIFrame.h"
#include "nsDOMError.h"
#include "nsIJSRuntimeService.h"
@ -73,12 +74,13 @@
#include "nsDOMError.h"
#include "nsContentUtils.h"
#include "nsServiceManagerUtils.h"
#include "nsIXPConnect.h"
#include "jsapi.h"
#include "cairo.h"
#include "gfxContext.h"
#include "glew.h"
#include "nsGLPbuffer.h"
@ -122,18 +124,16 @@ public:
// nsICanvasRenderingContextInternal
NS_IMETHOD SetCanvasElement(nsICanvasElement* aParentCanvas);
NS_IMETHOD SetDimensions(PRInt32 width, PRInt32 height);
NS_IMETHOD Render(nsIRenderingContext *rc);
NS_IMETHOD RenderToSurface(cairo_surface_t *surf);
NS_IMETHOD GetInputStream(const nsACString& aMimeType,
const nsAString& aEncoderOptions,
NS_IMETHOD Render(gfxContext *ctx);
NS_IMETHOD GetInputStream(const char* aMimeType,
const PRUnichar* aEncoderOptions,
nsIInputStream **aStream);
protected:
PRBool SafeToCreateCanvas3DContext();
nsIFrame *GetCanvasLayoutFrame();
nsresult DoSwapBuffers();
nsresult CairoSurfaceFromElement(nsIDOMElement *imgElt,
cairo_surface_t **aCairoSurface,
gfxASurface **aThebesSurface,
PRUint8 **imgData,
PRInt32 *widthOut, PRInt32 *heightOut,
nsIURI **uriOut, PRBool *forceWriteOnlyOut);
@ -412,6 +412,8 @@ public:
return PR_TRUE;
}
// We can't use ns*Substring, because we don't have internal linkage
#if 0
PRBool DefineProperty(const char *name, const nsCSubstring& val) {
JSString *jsstr = JS_NewStringCopyN(mCtx->ctx, val.BeginReading(), val.Length());
if (!jsstr ||
@ -427,6 +429,7 @@ public:
return PR_FALSE;
return PR_TRUE;
}
#endif
PRBool DefineProperty(const char *name, const char *val, PRUint32 len) {
JSString *jsstr = JS_NewStringCopyN(mCtx->ctx, val, len);

View File

@ -53,9 +53,7 @@
#include "nsICanvasGLPrivate.h"
#ifndef MOZILLA_1_8_BRANCH
#include "nsIDocument.h"
#endif
#include "nsTransform2D.h"
@ -73,28 +71,18 @@
#include "nsIImageLoadingContent.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIImage.h"
#include "nsIFrame.h"
#include "nsDOMError.h"
#include "nsIJSRuntimeService.h"
#ifndef MOZILLA_1_8_BRANCH
#include "nsIClassInfoImpl.h"
#endif
#include "nsServiceManagerUtils.h"
#include "nsDOMError.h"
#include "nsContentUtils.h"
#include "nsIXPConnect.h"
#include "jsapi.h"
#ifdef MOZ_CAIRO_GFX
#include "gfxContext.h"
#include "gfxASurface.h"
#endif
#ifdef XP_WIN
#include <windows.h>
#endif
@ -102,7 +90,8 @@
// GLEW will pull in the GL bits that we want/need
#include "glew.h"
#include "cairo.h"
#include "gfxImageSurface.h"
#include "gfxContext.h"
#ifdef PR_LOGGING
PRLogModuleInfo* gGLES11Log = nsnull;
@ -1132,13 +1121,14 @@ NS_IMETHODIMP
nsCanvasRenderingContextGLES11::TexImage2DHTML(PRUint32 target, nsIDOMHTMLElement *imageOrCanvas)
{
nsresult rv;
cairo_surface_t *cairo_surf = nsnull;
PRUint8 *image_data = nsnull, *local_image_data = nsnull;
nsRefPtr<gfxASurface> surf;
nsRefPtr<gfxImageSurface> tmpImageSurface;
PRUint8 *image_data = nsnull;
PRInt32 width, height;
nsCOMPtr<nsIURI> element_uri;
PRBool force_write_only = PR_FALSE;
rv = CairoSurfaceFromElement(imageOrCanvas, &cairo_surf, &image_data,
rv = CairoSurfaceFromElement(imageOrCanvas, getter_AddRefs(surf), &image_data,
&width, &height, getter_AddRefs(element_uri), &force_write_only);
if (NS_FAILED(rv))
return rv;
@ -1157,26 +1147,15 @@ nsCanvasRenderingContextGLES11::TexImage2DHTML(PRUint32 target, nsIDOMHTMLElemen
}
if (!image_data) {
local_image_data = (PRUint8*) PR_Malloc(width * height * 4);
if (!local_image_data)
return NS_ERROR_FAILURE;
nsRefPtr<gfxImageSurface> tmpImageSurface = new gfxImageSurface(gfxIntSize(width, height),
gfxASurface::ImageFormatARGB32);
cairo_surface_t *tmp = cairo_image_surface_create_for_data (local_image_data,
CAIRO_FORMAT_ARGB32,
width, height, width * 4);
if (!tmp) {
PR_Free(local_image_data);
return NS_ERROR_FAILURE;
}
nsRefPtr<gfxContext> cx = new gfxContext(tmpImageSurface);
cx->SetSource(surf);
cx->SetOperator(gfxContext::OPERATOR_SOURCE);
cx->Paint();
cairo_t *tmp_cr = cairo_create (tmp);
cairo_set_source_surface (tmp_cr, cairo_surf, 0, 0);
cairo_set_operator (tmp_cr, CAIRO_OPERATOR_SOURCE);
cairo_paint (tmp_cr);
cairo_destroy (tmp_cr);
cairo_surface_destroy (tmp);
image_data = local_image_data;
image_data = tmpImageSurface->Data();
}
// Er, I can do this with glPixelStore, no?
@ -1209,9 +1188,6 @@ nsCanvasRenderingContextGLES11::TexImage2DHTML(PRUint32 target, nsIDOMHTMLElemen
glTexImage2D(target, 0, 4, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data);
if (local_image_data)
PR_Free(local_image_data);
return NS_OK;
}

View File

@ -51,9 +51,7 @@
#include "nsIView.h"
#include "nsIViewManager.h"
#ifndef MOZILLA_1_8_BRANCH
#include "nsIDocument.h"
#endif
#include "nsTransform2D.h"
@ -71,28 +69,18 @@
#include "nsIImageLoadingContent.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsIImage.h"
#include "nsIFrame.h"
#include "nsDOMError.h"
#include "nsIJSRuntimeService.h"
#ifndef MOZILLA_1_8_BRANCH
#include "nsIClassInfoImpl.h"
#endif
#include "nsServiceManagerUtils.h"
#include "nsDOMError.h"
#include "nsContentUtils.h"
#include "nsIXPConnect.h"
#include "jsapi.h"
#ifdef MOZ_CAIRO_GFX
#include "gfxContext.h"
#include "gfxASurface.h"
#endif
#ifdef XP_WIN
#include <windows.h>
#endif
@ -102,7 +90,8 @@
// we're hoping that something is setting us up the remap
#include "cairo.h"
#include "gfxImageSurface.h"
#include "gfxContext.h"
#ifdef PR_LOGGING
PRLogModuleInfo* gGLES20Log = nsnull;
@ -1012,13 +1001,14 @@ NS_IMETHODIMP
nsCanvasRenderingContextGLWeb20::TexImage2DHTML(PRUint32 target, nsIDOMHTMLElement *imageOrCanvas)
{
nsresult rv;
cairo_surface_t *cairo_surf = nsnull;
PRUint8 *image_data = nsnull, *local_image_data = nsnull;
nsRefPtr<gfxASurface> surf;
nsRefPtr<gfxImageSurface> tmpImageSurface;
PRUint8 *image_data = nsnull;
PRInt32 width, height;
nsCOMPtr<nsIURI> element_uri;
PRBool force_write_only = PR_FALSE;
rv = CairoSurfaceFromElement(imageOrCanvas, &cairo_surf, &image_data,
rv = CairoSurfaceFromElement(imageOrCanvas, getter_AddRefs(surf), &image_data,
&width, &height, getter_AddRefs(element_uri), &force_write_only);
if (NS_FAILED(rv))
return rv;
@ -1037,26 +1027,15 @@ nsCanvasRenderingContextGLWeb20::TexImage2DHTML(PRUint32 target, nsIDOMHTMLEleme
}
if (!image_data) {
local_image_data = (PRUint8*) PR_Malloc(width * height * 4);
if (!local_image_data)
return NS_ERROR_FAILURE;
nsRefPtr<gfxImageSurface> tmpImageSurface = new gfxImageSurface(gfxIntSize(width, height),
gfxASurface::ImageFormatARGB32);
cairo_surface_t *tmp = cairo_image_surface_create_for_data (local_image_data,
CAIRO_FORMAT_ARGB32,
width, height, width * 4);
if (!tmp) {
PR_Free(local_image_data);
return NS_ERROR_FAILURE;
}
nsRefPtr<gfxContext> cx = new gfxContext(tmpImageSurface);
cx->SetSource(surf);
cx->SetOperator(gfxContext::OPERATOR_SOURCE);
cx->Paint();
cairo_t *tmp_cr = cairo_create (tmp);
cairo_set_source_surface (tmp_cr, cairo_surf, 0, 0);
cairo_set_operator (tmp_cr, CAIRO_OPERATOR_SOURCE);
cairo_paint (tmp_cr);
cairo_destroy (tmp_cr);
cairo_surface_destroy (tmp);
image_data = local_image_data;
image_data = tmpImageSurface->Data();
}
// Er, I can do this with glPixelStore, no?
@ -1089,9 +1068,6 @@ nsCanvasRenderingContextGLWeb20::TexImage2DHTML(PRUint32 target, nsIDOMHTMLEleme
glTexImage2D(target, 0, 4, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data);
if (local_image_data)
PR_Free(local_image_data);
return NS_OK;
}