WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
WIP patch
2d_acc.patch (text/plain), 19.43 KB, created by
Alejandro G. Castro
on 2012-12-11 07:51:20 PST
(
hide
)
Description:
WIP patch
Filename:
MIME Type:
Creator:
Alejandro G. Castro
Created:
2012-12-11 07:51:20 PST
Size:
19.43 KB
patch
obsolete
>diff --git a/Source/WebCore/GNUmakefile.am b/Source/WebCore/GNUmakefile.am >index 594bda0..fc1e8e5a 100644 >--- a/Source/WebCore/GNUmakefile.am >+++ b/Source/WebCore/GNUmakefile.am >@@ -347,6 +347,15 @@ feature_defines_overrides += ENABLE_WEBGL=0 > endif # END ENABLE_WEBGL > > # --- >+# Accelerated 2D canvas >+# --- >+if ENABLE_ACCELERATED_2D_CANVAS >+feature_defines_overrides += ENABLE_ACCELERATED_2D_CANVAS=1 >+else >+feature_defines_overrides += ENABLE_ACCELERATED_2D_CANVAS=0 >+endif # ENABLE_ACCELERATED_2D_CANVAS >+ >+# --- > # Accelerated compositing support > # --- > if USE_ACCELERATED_COMPOSITING >diff --git a/Source/WebCore/platform/graphics/GraphicsContext.cpp b/Source/WebCore/platform/graphics/GraphicsContext.cpp >index a5a16da..db1c313 100644 >--- a/Source/WebCore/platform/graphics/GraphicsContext.cpp >+++ b/Source/WebCore/platform/graphics/GraphicsContext.cpp >@@ -735,7 +735,7 @@ void GraphicsContext::setPlatformShouldSmoothFonts(bool) > } > #endif > >-#if !USE(SKIA) && !USE(CG) >+#if !USE(SKIA) && !USE(CG) && !USE(CAIRO) > bool GraphicsContext::isAcceleratedContext() const > { > return false; >diff --git a/Source/WebCore/platform/graphics/ImageBuffer.cpp b/Source/WebCore/platform/graphics/ImageBuffer.cpp >index fbcfb59..8a1b167 100644 >--- a/Source/WebCore/platform/graphics/ImageBuffer.cpp >+++ b/Source/WebCore/platform/graphics/ImageBuffer.cpp >@@ -99,7 +99,7 @@ void ImageBuffer::convertToLuminanceMask() > genericConvertToLuminanceMask(); > } > >-#if USE(ACCELERATED_COMPOSITING) && !USE(SKIA) >+#if USE(ACCELERATED_COMPOSITING) && !USE(SKIA) && !USE(CAIRO) > PlatformLayer* ImageBuffer::platformLayer() const > { > return 0; >diff --git a/Source/WebCore/platform/graphics/cairo/GLContext.h b/Source/WebCore/platform/graphics/cairo/GLContext.h >index 1a88072..b6c00e4 100644 >--- a/Source/WebCore/platform/graphics/cairo/GLContext.h >+++ b/Source/WebCore/platform/graphics/cairo/GLContext.h >@@ -29,6 +29,8 @@ > typedef struct _XDisplay Display; > #endif > >+typedef struct _cairo_device cairo_device_t; >+ > namespace WebCore { > > class GLContext { >@@ -46,6 +48,7 @@ public: > virtual void waitNative() = 0; > virtual bool canRenderToDefaultFramebuffer() = 0; > virtual IntSize defaultFrameBufferSize() = 0; >+ virtual cairo_device_t* cairoDevice() = 0; > > #if PLATFORM(X11) > static Display* sharedX11Display(); >diff --git a/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp >index 3524887..666e48c 100644 >--- a/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp >+++ b/Source/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp >@@ -1155,6 +1155,11 @@ InterpolationQuality GraphicsContext::imageInterpolationQuality() const > return platformContext()->imageInterpolationQuality(); > } > >+bool GraphicsContext::isAcceleratedContext() const >+{ >+ return cairo_surface_get_type(cairo_get_target(platformContext()->cr())) == CAIRO_SURFACE_TYPE_GL; >+} >+ > #if ENABLE(3D_RENDERING) && USE(TEXTURE_MAPPER) > TransformationMatrix GraphicsContext::get3DTransform() const > { >diff --git a/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp b/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp >index b3d13fd..9831089 100644 >--- a/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp >+++ b/Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp >@@ -32,6 +32,7 @@ > #include "BitmapImage.h" > #include "CairoUtilities.h" > #include "Color.h" >+#include "GLContext.h" > #include "GraphicsContext.h" > #include "ImageData.h" > #include "MIMETypeRegistry.h" >@@ -40,29 +41,77 @@ > #include "PlatformContextCairo.h" > #include "RefPtrCairo.h" > #include <cairo.h> >+#include <cairo-gl.h> > #include <wtf/Vector.h> > #include <wtf/text/Base64.h> > #include <wtf/text/WTFString.h> > >+#if USE(TEXTURE_MAPPER_GL) >+#include "TextureMapperGL.h" >+#endif >+ > using namespace std; > > namespace WebCore { > >-ImageBufferData::ImageBufferData(const IntSize&) >- : m_surface(0) >+ImageBufferData::ImageBufferData(const IntSize& size) >+ : m_size(size) >+ , m_surface(0) > , m_platformContext(0) >+ , m_texture(0) > { > } > >-ImageBuffer::ImageBuffer(const IntSize& size, float /* resolutionScale */, ColorSpace, RenderingMode, DeferralMode, bool& success) >+#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) >+void ImageBufferData::paintToTextureMapper(TextureMapper* textureMapper, const FloatRect& targetRect, const TransformationMatrix& matrix, float opacity, BitmapTexture* mask) >+{ >+ if (textureMapper->accelerationMode() != TextureMapper::OpenGLMode) { >+ notImplemented(); >+ return; >+ } >+ >+#if USE(TEXTURE_MAPPER_GL) >+ ASSERT(m_texture); >+ >+ // Cairo may change the active context, so we make sure to change it back after flushing. >+ GLContext* previousActiveContext = GLContext::getCurrent(); >+ cairo_surface_flush(m_surface); >+ previousActiveContext->makeContextCurrent(); >+ >+ TextureMapperGL* texmapGL = static_cast<TextureMapperGL*>(textureMapper); >+ TextureMapperGL::Flags flags = TextureMapperGL::SupportsBlending; >+ texmapGL->drawTexture(m_texture, flags, m_size, targetRect, matrix, opacity, mask); >+#endif >+} >+#endif >+ >+ImageBuffer::ImageBuffer(const IntSize& size, float /* resolutionScale */, ColorSpace, RenderingMode renderingMode, DeferralMode, bool& success) > : m_data(size) > , m_size(size) > , m_logicalSize(size) > { > success = false; // Make early return mean error. >- m_data.m_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, >- size.width(), >- size.height()); >+ >+ if (renderingMode == Accelerated) { >+ GLContext::sharingContext()->makeContextCurrent(); >+ >+ glGenTextures(1, &m_data.m_texture); >+ glBindTexture(GL_TEXTURE_2D, m_data.m_texture); >+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); >+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); >+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); >+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); >+ >+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1); >+ >+ glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA8, m_size.width(), m_size.height(), 0 /* border */, GL_RGBA, GL_UNSIGNED_BYTE, NULL); >+ >+ m_data.m_surface = cairo_gl_surface_create_for_texture(GLContext::sharingContext()->cairoDevice(), >+ CAIRO_CONTENT_COLOR_ALPHA, m_data.m_texture, >+ size.width(), size.height()); >+ } else >+ m_data.m_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, size.width(), size.height()); >+ > if (cairo_surface_status(m_data.m_surface) != CAIRO_STATUS_SUCCESS) > return; // create will notice we didn't set m_initialized and fail. > >@@ -113,7 +162,9 @@ void ImageBuffer::drawPattern(GraphicsContext* context, const FloatRect& srcRect > > void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable) > { >- ASSERT(cairo_surface_get_type(m_data.m_surface) == CAIRO_SURFACE_TYPE_IMAGE); >+ // FIXME: Disable color space conversions on accelerated canvases (for now). >+ if (cairo_surface_get_type(m_data.m_surface) != CAIRO_SURFACE_TYPE_IMAGE) >+ return; > > unsigned char* dataSrc = cairo_image_surface_get_data(m_data.m_surface); > int stride = cairo_image_surface_get_stride(m_data.m_surface); >@@ -132,13 +183,47 @@ void ImageBuffer::platformTransformColorSpace(const Vector<int>& lookUpTable) > cairo_surface_mark_dirty_rectangle (m_data.m_surface, 0, 0, m_size.width(), m_size.height()); > } > >+static cairo_surface_t* mapSurfaceToImage(cairo_surface_t* surface, const IntSize& size) >+{ >+ if (cairo_surface_get_type(surface) == CAIRO_SURFACE_TYPE_IMAGE) >+ return surface; >+ >+ cairo_surface_t* imageSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, size.width(), size.height()); >+ RefPtr<cairo_t> cr = adoptRef(cairo_create(imageSurface)); >+ cairo_set_source_surface(cr.get(), surface, 0, 0); >+ cairo_paint(cr.get()); >+ return imageSurface; >+} >+ >+static void unmapSurfaceFromImage(cairo_surface_t* surface, cairo_surface_t* imageSurface, const IntRect& dirtyRectangle = IntRect()) >+{ >+ if (surface == imageSurface && dirtyRectangle.isEmpty()) >+ return; >+ if (dirtyRectangle.isEmpty()) { >+ cairo_surface_destroy(imageSurface); >+ return; >+ } >+ >+ if (surface == imageSurface) { >+ cairo_surface_mark_dirty_rectangle(surface, >+ dirtyRectangle.x(), dirtyRectangle.width(), >+ dirtyRectangle.width(), dirtyRectangle.height()); >+ return; >+ } >+ >+ RefPtr<cairo_t> cr = adoptRef(cairo_create(surface)); >+ cairo_set_source_surface(cr.get(), imageSurface, 0, 0); >+ cairo_rectangle(cr.get(), dirtyRectangle.x(), dirtyRectangle.y(), dirtyRectangle.width(), dirtyRectangle.height()); >+ cairo_fill(cr.get()); >+ cairo_surface_destroy(imageSurface); >+} >+ > template <Multiply multiplied> > PassRefPtr<Uint8ClampedArray> getImageData(const IntRect& rect, const ImageBufferData& data, const IntSize& size) > { >- ASSERT(cairo_surface_get_type(data.m_surface) == CAIRO_SURFACE_TYPE_IMAGE); >- > RefPtr<Uint8ClampedArray> result = Uint8ClampedArray::createUninitialized(rect.width() * rect.height() * 4); >- unsigned char* dataSrc = cairo_image_surface_get_data(data.m_surface); >+ cairo_surface_t* imageSurface = mapSurfaceToImage(data.m_surface, size); >+ unsigned char* dataSrc = cairo_image_surface_get_data(imageSurface); > unsigned char* dataDst = result->data(); > > if (rect.x() < 0 || rect.y() < 0 || (rect.x() + rect.width()) > size.width() || (rect.y() + rect.height()) > size.height()) >@@ -199,6 +284,7 @@ PassRefPtr<Uint8ClampedArray> getImageData(const IntRect& rect, const ImageBuffe > destRows += destBytesPerRow; > } > >+ unmapSurfaceFromImage(data.m_surface, imageSurface); > return result.release(); > } > >@@ -214,9 +300,8 @@ PassRefPtr<Uint8ClampedArray> ImageBuffer::getPremultipliedImageData(const IntRe > > void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, CoordinateSystem) > { >- ASSERT(cairo_surface_get_type(m_data.m_surface) == CAIRO_SURFACE_TYPE_IMAGE); >- >- unsigned char* dataDst = cairo_image_surface_get_data(m_data.m_surface); >+ cairo_surface_t* imageSurface = mapSurfaceToImage(m_data.m_surface, sourceSize); >+ unsigned char* dataDst = cairo_image_surface_get_data(imageSurface); > > ASSERT(sourceRect.width() > 0); > ASSERT(sourceRect.height() > 0); >@@ -245,7 +330,7 @@ void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, c > int numRows = endy - desty; > > unsigned srcBytesPerRow = 4 * sourceSize.width(); >- int stride = cairo_image_surface_get_stride(m_data.m_surface); >+ int stride = cairo_image_surface_get_stride(imageSurface); > > unsigned char* srcRows = source->data() + originy * srcBytesPerRow + originx * 4; > for (int y = 0; y < numRows; ++y) { >@@ -273,9 +358,8 @@ void ImageBuffer::putByteArray(Multiply multiplied, Uint8ClampedArray* source, c > } > srcRows += srcBytesPerRow; > } >- cairo_surface_mark_dirty_rectangle(m_data.m_surface, >- destx, desty, >- numColumns, numRows); >+ >+ unmapSurfaceFromImage(m_data.m_surface, imageSurface, IntRect(destx, desty, numColumns, numRows)); > } > > #if !PLATFORM(GTK) >@@ -310,4 +394,11 @@ String ImageBuffer::toDataURL(const String& mimeType, const double*, CoordinateS > } > #endif > >+PlatformLayer* ImageBuffer::platformLayer() const >+{ >+ if (m_data.m_texture) >+ return const_cast<ImageBufferData*>(&m_data); >+ return 0; >+} >+ > } // namespace WebCore >diff --git a/Source/WebCore/platform/graphics/cairo/ImageBufferDataCairo.h b/Source/WebCore/platform/graphics/cairo/ImageBufferDataCairo.h >index 5ca7262..7a93cde 100644 >--- a/Source/WebCore/platform/graphics/cairo/ImageBufferDataCairo.h >+++ b/Source/WebCore/platform/graphics/cairo/ImageBufferDataCairo.h >@@ -25,18 +25,33 @@ > > #include "PlatformContextCairo.h" > >+#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) >+#include "TextureMapper.h" >+#endif >+ > typedef struct _cairo_surface cairo_surface_t; > > namespace WebCore { > > class IntSize; >+class ImageBufferPlatformLayer; > >-class ImageBufferData { >+class ImageBufferData >+#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) >+ : public TextureMapperPlatformLayer >+#endif >+{ > public: > ImageBufferData(const IntSize&); > >+ IntSize m_size; > cairo_surface_t* m_surface; > PlatformContextCairo m_platformContext; >+ >+#if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) >+ virtual void paintToTextureMapper(TextureMapper*, const FloatRect& target, const TransformationMatrix&, float opacity, BitmapTexture* mask); >+ uint32_t m_texture; >+#endif > }; > > } // namespace WebCore >diff --git a/Source/WebCore/platform/graphics/egl/GLContextEGL.cpp b/Source/WebCore/platform/graphics/egl/GLContextEGL.cpp >index b9389b4..ca42a66 100644 >--- a/Source/WebCore/platform/graphics/egl/GLContextEGL.cpp >+++ b/Source/WebCore/platform/graphics/egl/GLContextEGL.cpp >@@ -22,6 +22,8 @@ > #if USE(EGL) > > #include "GraphicsContext3D.h" >+#include <cairo.h> >+#include <cairo-gl.h> > #include <wtf/OwnPtr.h> > > #if USE(OPENGL_ES_2) >@@ -208,11 +210,15 @@ GLContextEGL::GLContextEGL(EGLContext context, EGLSurface surface, EGLSurfaceTyp > : m_context(context) > , m_surface(surface) > , m_type(type) >+ , m_cairoDevice(0) > { > } > > GLContextEGL::~GLContextEGL() > { >+ if (m_cairoDevice) >+ cairo_device_destroy(m_cairoDevice); >+ > EGLDisplay display = sharedEGLDisplay(); > if (m_context) { > glBindFramebuffer(GL_FRAMEBUFFER, 0); >@@ -224,6 +230,15 @@ GLContextEGL::~GLContextEGL() > eglDestroySurface(display, m_surface); > } > >+cairo_device_t* GLContextEGL::cairoDevice() >+{ >+ if (m_cairoDevice) >+ return m_cairoDevice; >+ >+ m_cairoDevice = cairo_egl_device_create(sharedEGLDisplay(), m_context); >+ return m_cairoDevice; >+} >+ > bool GLContextEGL::canRenderToDefaultFramebuffer() > { > return m_type == WindowSurface; >diff --git a/Source/WebCore/platform/graphics/egl/GLContextEGL.h b/Source/WebCore/platform/graphics/egl/GLContextEGL.h >index c5d4bf7..91e7365 100644 >--- a/Source/WebCore/platform/graphics/egl/GLContextEGL.h >+++ b/Source/WebCore/platform/graphics/egl/GLContextEGL.h >@@ -41,6 +41,7 @@ public: > virtual void waitNative(); > virtual bool canRenderToDefaultFramebuffer(); > virtual IntSize defaultFrameBufferSize(); >+ virtual cairo_device_t* cairoDevice(); > > > #if ENABLE(WEBGL) >@@ -59,6 +60,7 @@ private: > EGLContext m_context; > EGLSurface m_surface; > EGLSurfaceType m_type; >+ cairo_device_t* m_cairoDevice; > }; > > } // namespace WebCore >diff --git a/Source/WebCore/platform/graphics/glx/GLContextGLX.cpp b/Source/WebCore/platform/graphics/glx/GLContextGLX.cpp >index 31f32cf..253e664 100644 >--- a/Source/WebCore/platform/graphics/glx/GLContextGLX.cpp >+++ b/Source/WebCore/platform/graphics/glx/GLContextGLX.cpp >@@ -23,6 +23,8 @@ > #include "GraphicsContext3D.h" > #include "OpenGLShims.h" > #include <GL/glx.h> >+#include <cairo.h> >+#include <cairo-gl.h> > #include <wtf/OwnPtr.h> > > namespace WebCore { >@@ -168,6 +170,7 @@ GLContextGLX::GLContextGLX(GLXContext context) > , m_pbuffer(0) > , m_pixmap(0) > , m_glxPixmap(0) >+ , m_cairoDevice(0) > { > } > >@@ -182,6 +185,9 @@ GLContextGLX::GLContextGLX(GLXContext context, Pixmap pixmap, GLXPixmap glxPixma > > GLContextGLX::~GLContextGLX() > { >+ if (m_cairoDevice) >+ cairo_device_destroy(m_cairoDevice); >+ > if (m_context) { > // This may be necessary to prevent crashes with NVidia's closed source drivers. Originally > // from Mozilla's 3D canvas implementation at: http://bitbucket.org/ilmari/canvas3d/ >@@ -251,6 +257,15 @@ void GLContextGLX::waitNative() > glXWaitX(); > } > >+cairo_device_t* GLContextGLX::cairoDevice() >+{ >+ if (m_cairoDevice) >+ return m_cairoDevice; >+ >+ m_cairoDevice = cairo_glx_device_create(sharedX11Display(), m_context); >+ return m_cairoDevice; >+} >+ > #if USE(3D_GRAPHICS) > PlatformGraphicsContext3D GLContextGLX::platformContext() > { >diff --git a/Source/WebCore/platform/graphics/glx/GLContextGLX.h b/Source/WebCore/platform/graphics/glx/GLContextGLX.h >index 888146b..596de9f 100644 >--- a/Source/WebCore/platform/graphics/glx/GLContextGLX.h >+++ b/Source/WebCore/platform/graphics/glx/GLContextGLX.h >@@ -51,6 +51,8 @@ public: > virtual PlatformGraphicsContext3D platformContext(); > #endif > >+ virtual cairo_device_t* cairoDevice(); >+ > private: > static PassOwnPtr<GLContextGLX> createPbufferContext(GLXContext sharingContext); > static PassOwnPtr<GLContextGLX> createPixmapContext(GLXContext sharingContext); >@@ -63,6 +65,7 @@ private: > GLXPbuffer m_pbuffer; > Pixmap m_pixmap; > GLXPixmap m_glxPixmap; >+ cairo_device_t* m_cairoDevice; > }; > > } // namespace WebCore >diff --git a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp >index 7a49d71..2c9fa3a 100644 >--- a/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp >+++ b/Source/WebCore/platform/graphics/texmap/GraphicsLayerTextureMapper.cpp >@@ -413,6 +413,9 @@ void GraphicsLayerTextureMapper::flushCompositingStateForThisLayerOnly() > */ > void GraphicsLayerTextureMapper::flushCompositingState(const FloatRect&) > { >+ if (!m_layer->textureMapper()) >+ return; >+ > m_layer->flushCompositingState(this, TextureMapperLayer::TraverseDescendants); > didFlushCompositingStateRecursive(); > } >diff --git a/configure.ac b/configure.ac >index f5f4d90..f30dbd3 100644 >--- a/configure.ac >+++ b/configure.ac >@@ -688,6 +688,14 @@ AC_ARG_ENABLE(accelerated_compositing, > ]) > AC_MSG_RESULT([$enable_accelerated_compositing]) > >+# check whether to enable acceleratd 2D canvas >+AC_MSG_CHECKING([whether to enable accelerated 2D canvas support]) >+AC_ARG_ENABLE(acelerated_2d_canvas, >+ AC_HELP_STRING([--enable-accelerated-2d-canvas], >+ [enable accelerated 2D canvas [default=no]]), >+ [],[enable_accelerated_2d_canvas="yes"]) >+AC_MSG_RESULT([$enable_accelerated_2d_canvas]) >+ > # check whether to enable Gamepad support > AC_MSG_CHECKING([whether to enable Gamepad support]) > AC_ARG_ENABLE(gamepad, >@@ -1210,6 +1218,7 @@ AM_CONDITIONAL([ENABLE_DEBUG],[test "$enable_debug_features" = "yes"]) > AM_CONDITIONAL([ENABLE_UNSTABLE_FEATURES],[test "$enable_unstable_features" = "yes"]) > AM_CONDITIONAL([ENABLE_WEBGL],[test "$enable_webgl" = "yes"]) > AM_CONDITIONAL([ENABLE_GAMEPAD],[test "$enable_gamepad" = "yes"]) >+AM_CONDITIONAL([ENABLE_ACCELERATED_2D_CANVAS],[test "$enable_accelerated_2d_canvas" = "yes"]) > AM_CONDITIONAL([ENABLE_XHR_TIMEOUT],[test "$enable_xhr_timeout" = "yes"]) > AM_CONDITIONAL([ENABLE_XSLT],[test "$enable_xslt" = "yes"]) > AM_CONDITIONAL([ENABLE_FILTERS],[test "$enable_filters" = "yes"]) >@@ -1299,6 +1308,7 @@ Features: > Spellcheck support : $enable_spellcheck > Web Audio support : $enable_web_audio > WebGL : $enable_webgl >+ Accelerated 2D canvas support : $enable_accelerated_2d_canvas > XHR timeout support : $enable_xhr_timeout > XSLT support : $enable_xslt >
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Flags:
eflews.bot
:
commit-queue-
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 104672
:
178805
|
180659
|
197390
|
197396