Bug 122589 - Graphics backend without hardware accelerated compositing, and compositing disabled by Setting, causes the CSS3 Transform discarding perspective component, only affine part remains
Summary: Graphics backend without hardware accelerated compositing, and compositing di...
Status: RESOLVED INVALID
Alias: None
Product: WebKit
Classification: Unclassified
Component: CSS (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P1 Major
Assignee: Nobody
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-10-09 23:10 PDT by Chen Zhixiang
Modified: 2015-04-24 21:09 PDT (History)
1 user (show)

See Also:


Attachments
Test case, displayed wrong when compositing disabled in Setting (572 bytes, text/html)
2013-10-09 23:10 PDT, Chen Zhixiang
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Chen Zhixiang 2013-10-09 23:10:33 PDT
Created attachment 213855 [details]
Test case, displayed wrong when compositing disabled in Setting

Our org. has 2 internal WebKit based customization projects,
One is using WinCE port with Google V8 and Skia (2012/8 edition), the other is using Qt port with Qt-4.8 xlibgl backend(compositing disbaled),
The 2 have both the same error:
With the following CSS3 transform test case, the display result is wrong, compared to Firefox 24 and Chrome 30.

    #imgElement{
        -webkit-transform: perspective(300px) rotateX(60deg);
        opacity: 1.0;
    }

The above CSS3 transform rule should make the image's above part shorter and tilt toward the middle, but in fact they are displayed as if screwed to right.
I doesn't know why and tried to figure out the evil.

I've located to function "makeMatrixRenderable" which is at our WebKit edtion is in RenderObject.h, but now moved to RenderLayer.cpp

inline void makeMatrixRenderable(TransformationMatrix& matrix, bool has3DRendering)
{
#if !ENABLE(3D_RENDERING)
    UNUSED_PARAM(has3DRendering);
1>    matrix.makeAffine();  //(1)
#else
    if (!has3DRendering)
2>        matrix.makeAffine();  //(2)
#endif
}

If compositing is disabled, the paramter has3DRendering is false. Normally has3DRendering is true, though the graphics backend may not support accelerated compositing.

Our WinCE port running will match the (1) line positin, and our Qt-4.8 xlibgl port running will match the (2) line position. Both changes the matrix data.

I've commented the matrix.makeAffine(); to test, which is still wrong. So there MUST be a in-consistence somewhere else.

Can anyone kindly help with this problem? 3x!
Comment 1 Chen Zhixiang 2013-10-09 23:16:29 PDT
When debugging, there are different Affine Transform related to this "perspective(300px) rotateX(60deg)" transform rule:

Qt-4.8 xlibgl backend: (wrong)
concatCTM: transform={1.000000,0.000000,-0.577350,0.359993,78.001488,231.040361}

Qt-4.8 xlib backend(ENABLE(3D_RENDERING)=1): (right)
concat3DTransform: transform={1.000000,0.000000,-0.721688,-0.217358,85.001860,259.041849}

Qt-4.8 compiled on Windows/GDI: (right)
concat3DTransform: transform={1.000000,0.000000,-0.721688,-0.217358,85.001860,259.041849}

WinCE: (wrong)
concatCTM: transform={1.000000,0.000000,-0.577350,0.359993,78.001488,231.040361}
Comment 2 Chen Zhixiang 2013-10-09 23:20:10 PDT
Bug 24396 seems related.

Here, what's the relationship between ENABLE(3D_TRANSFORMS)、ENABLE(3D_RENDERING) and USE(ACCELERATED_COMPOSITING)?
Comment 3 Chen Zhixiang 2013-10-09 23:39:30 PDT
Disabling compositing method:

void RenderLayerCompositor::cacheAcceleratedCompositingFlags() 
{ 
    bool hasAcceleratedCompositing = false; 
    bool showDebugBorders = false; 
    bool showRepaintCounter = false; 
    bool forceCompositingMode = false; 

    if (Settings* settings = m_renderView->document()->settings()) { 
〉 hasAcceleratedCompositing = false; //settings->acceleratedCompositingEnabled(); 

        // We allow the chrome to override the settings, in case the page is rendered 
        // on a chrome that doesn't allow accelerated compositing. 
        if (hasAcceleratedCompositing) { 
            Frame* frame = m_renderView->frameView()->frame(); 
            Page* page = frame ? frame->page() : 0; 
            if (page) { 
                ChromeClient* chromeClient = page->chrome()->client(); 
                m_compositingTriggers = chromeClient->allowedCompositingTriggers(); 
                hasAcceleratedCompositing = m_compositingTriggers; 
            } 
        } 

After applying the change to Qt-4.8 Windows GDI port, the result becomes wrong!

I have to say, the CSS3 transform should be right, no matter whether or not settings->acceleratedCompositingEnabled() is true/false.
Comment 4 Chen Zhixiang 2013-10-13 22:01:57 PDT
It seems that, when acceleratedCompositing is disabled, then only the affine transform component in 3D transform is applied to element, the perspective part is disgarded.

This is definitely a bug.

But how could I fill/fix the gap between no-3d-accelerated-compositing and anyway supporting the perspective transform?

The Qt-4.8/xlib port of WebKit uses the texmap/TextureMapperImageBuffer, -- but the Qt-4.8/xlibgl port does NOT.
Comment 5 Chen Zhixiang 2013-10-14 21:08:11 PDT
I've fixed this problem for Qt-4.8 port with xlibgl but combining 2 modifications:

(1)enforce hardware accelerated compositing: 
gedit Source/WebCore/rendering/RenderLayerCompositor.cpp & 

void RenderLayerCompositor::cacheAcceleratedCompositingFlags() 
{ 
    bool hasAcceleratedCompositing = false; 
    bool showDebugBorders = false; 
    bool showRepaintCounter = false; 
    bool forceCompositingMode = false; 

    if (Settings* settings = m_renderView->document()->settings()) { 
> hasAcceleratedCompositing = true; //settings->acceleratedCompositingEnabled();
... 

(2)Use TextureMapperImageBuffer instead of TextureMapperGL
gedit Source/WebKit/qt/WebCoreSupport/PageClientQt.cpp & 

#if USE(TEXTURE_MAPPER) 
void PageClientQGraphicsWidget::setRootGraphicsLayer(GraphicsLayer* layer) 
{ 
    if (layer) { 
        TextureMapperLayerClient = adoptPtr(new TextureMapperLayerClientQt(page->mainFrame(), layer)); 
#if USE(TEXTURE_MAPPER_GL) 
        QGraphicsView* graphicsView = view->scene()->views()[0]; 
        if (graphicsView && graphicsView->viewport() && graphicsView->viewport()->inherits("QGLWidget")) { 
            printf("setRootGraphicsLayer: USE(TEXTURE_MAPPER) & call TextureMapper::create(TextureMapper::OpenGLMode)\n"); 
            //TextureMapperLayerClient->setTextureMapper(TextureMapper::create(TextureMapper::OpenGLMode)); 
〉 TextureMapperLayerClient->setTextureMapper(TextureMapper::create()); 
            return; 
        } 
#endif 
        printf("setRootGraphicsLayer: USE(TEXTURE_MAPPER) & call TextureMapper::create()\n"); 
        TextureMapperLayerClient->setTextureMapper(TextureMapper::create()); 
        return; 
    } 
    TextureMapperLayerClient.clear(); 
}

The key point is, to make perpective transform which is NOT 2D-affine transform effectful, we MUST use the TextureMapperImageBuffer implementation!
Comment 6 Chen Zhixiang 2013-10-14 21:09:08 PDT
Since Qt port is now un-supported in newest WebKit trunk, i post this to be somehow help for others!
Comment 7 Martin Robinson 2015-04-24 21:09:40 PDT
Closing this as it seems to be an issue with QtWebKit which is no longer part of WebKit.