Bug 607936 - Make possible to apply transform on topLevel LayerManager scene r=matt,roc a=joe

--HG--
extra : rebase_source : 7983ed59e06d33e5c17878a24434eef409684d25
This commit is contained in:
Oleg Romashin 2011-02-04 14:47:06 -05:00
Родитель 1128a62a40
Коммит db3832bc1b
4 изменённых файлов: 68 добавлений и 5 удалений

Просмотреть файл

@ -211,7 +211,8 @@ ContainerRender(Container* aContainer,
childOffset.y = visibleRect.y;
aContainer->gl()->PushViewportRect();
aManager->SetupPipeline(visibleRect.width, visibleRect.height);
aManager->SetupPipeline(visibleRect.width, visibleRect.height,
LayerManagerOGL::DontApplyWorldTransform);
} else {
frameBuffer = aPreviousFrameBuffer;
@ -256,6 +257,11 @@ ContainerRender(Container* aContainer,
if (needsFramebuffer) {
scissorRect.MoveBy(- visibleRect.TopLeft());
} else {
if (!frameBuffer) {
// Transform scissorRect here
aManager->WorldTransformRect(scissorRect);
}
if (!aPreviousFrameBuffer) {
/**
* glScissor coordinates are oriented with 0,0 being at the bottom left,
@ -298,7 +304,8 @@ ContainerRender(Container* aContainer,
// Restore the viewport
aContainer->gl()->PopViewportRect();
nsIntRect viewport = aContainer->gl()->ViewportRect();
aManager->SetupPipeline(viewport.width, viewport.height);
aManager->SetupPipeline(viewport.width, viewport.height,
LayerManagerOGL::ApplyWorldTransform);
aContainer->gl()->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, aPreviousFrameBuffer);
aContainer->gl()->fDeleteFramebuffers(1, &frameBuffer);

Просмотреть файл

@ -550,6 +550,7 @@ LayerManagerOGL::Render()
nsIntRect rect;
mWidget->GetClientBounds(rect);
WorldTransformRect(rect);
GLint width = rect.width;
GLint height = rect.height;
@ -575,7 +576,7 @@ LayerManagerOGL::Render()
DEBUG_GL_ERROR_CHECK(mGLContext);
SetupBackBuffer(width, height);
SetupPipeline(width, height);
SetupPipeline(width, height, ApplyWorldTransform);
// Default blend function implements "OVER"
mGLContext->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE_MINUS_SRC_ALPHA,
@ -588,6 +589,7 @@ LayerManagerOGL::Render()
if (clipRect) {
nsIntRect r = *clipRect;
WorldTransformRect(r);
if (!mGLContext->IsDoubleBuffered() && !mTarget)
mGLContext->FixWindowCoordinateRect(r, mWidgetSize.height);
mGLContext->fScissor(r.x, r.y, r.width, r.height);
@ -662,6 +664,8 @@ LayerManagerOGL::Render()
nsIntRegionRectIterator iter(mClippingRegion);
while ((r = iter.Next()) != nsnull) {
nsIntRect cRect = *r; r = &cRect;
WorldTransformRect(cRect);
float left = (GLfloat)r->x / width;
float right = (GLfloat)r->XMost() / width;
float top = (GLfloat)r->y / height;
@ -706,7 +710,32 @@ LayerManagerOGL::Render()
}
void
LayerManagerOGL::SetupPipeline(int aWidth, int aHeight)
LayerManagerOGL::SetWorldTransform(const gfxMatrix& aMatrix)
{
NS_ASSERTION(aMatrix.PreservesAxisAlignedRectangles(),
"SetWorldTransform only accepts matrices that satisfy PreservesAxisAlignedRectangles");
NS_ASSERTION(!aMatrix.HasNonIntegerScale(),
"SetWorldTransform only accepts matrices with integer scale");
mWorldMatrix = aMatrix;
}
gfxMatrix&
LayerManagerOGL::GetWorldTransform(void)
{
return mWorldMatrix;
}
void
LayerManagerOGL::WorldTransformRect(nsIntRect& aRect)
{
gfxRect grect(aRect.x, aRect.y, aRect.width, aRect.height);
grect = mWorldMatrix.TransformBounds(grect);
aRect.SetRect(grect.pos.x, grect.pos.y, grect.size.width, grect.size.height);
}
void
LayerManagerOGL::SetupPipeline(int aWidth, int aHeight, WorldTransforPolicy aTransformPolicy)
{
// Set the viewport correctly.
//
@ -744,6 +773,10 @@ LayerManagerOGL::SetupPipeline(int aWidth, int aHeight)
viewMatrix._42 = -1.0f;
}
if (aTransformPolicy == ApplyWorldTransform) {
viewMatrix = gfx3DMatrix::From2D(mWorldMatrix) * viewMatrix;
}
SetLayerProgramProjectionMatrix(viewMatrix);
}

Просмотреть файл

@ -372,11 +372,25 @@ public:
return mWidgetSize;
}
enum WorldTransforPolicy {
ApplyWorldTransform,
DontApplyWorldTransform
};
/**
* Setup the viewport and projection matrix for rendering
* to a window of the given dimensions.
*/
void SetupPipeline(int aWidth, int aHeight);
void SetupPipeline(int aWidth, int aHeight, WorldTransforPolicy aTransformPolicy);
/**
* Setup World transform matrix.
* Transform will be ignored if it is not PreservesAxisAlignedRectangles
* or has non integer scale
*/
void SetWorldTransform(const gfxMatrix& aMatrix);
gfxMatrix& GetWorldTransform(void);
void WorldTransformRect(nsIntRect& aRect);
private:
/** Widget associated with this layer manager */
@ -455,6 +469,7 @@ private:
* while rendering */
DrawThebesLayerCallback mThebesLayerCallback;
void *mThebesLayerCallbackData;
gfxMatrix mWorldMatrix;
};
/**

Просмотреть файл

@ -281,6 +281,14 @@ public:
|| (FuzzyEqual(xy, 0.0) && FuzzyEqual(yx, 0.0)));
}
/**
* Returns true if the matrix has non-integer scale
*/
PRBool HasNonIntegerScale() const {
return !FuzzyEqual(xx, NS_floor(xx + 0.5)) ||
!FuzzyEqual(yy, NS_floor(yy + 0.5));
}
private:
static PRBool FuzzyEqual(gfxFloat aV1, gfxFloat aV2) {
return fabs(aV2 - aV1) < 1e-6;