Bug 546515: Part 1: Add a layers backend based on Direct3D9. r=jrmuizel

This commit is contained in:
Bas Schouten 2010-05-24 17:28:51 +02:00
parent 8fb86df3e7
commit 5c0ef5136a
16 changed files with 3078 additions and 1 deletions

View File

@ -122,7 +122,8 @@ class THEBES_API LayerManager {
public:
enum LayersBackend {
LAYERS_BASIC = 0,
LAYERS_OPENGL
LAYERS_OPENGL,
LAYERS_D3D9
};
virtual ~LayerManager() {}

View File

@ -42,6 +42,7 @@ VPATH = \
$(srcdir) \
$(srcdir)/basic \
$(srcdir)/opengl \
$(srcdir)/d3d9 \
$(NULL)
include $(DEPTH)/config/autoconf.mk
@ -52,6 +53,9 @@ LIBXUL_LIBRARY = 1
FORCE_STATIC_LIB = 1
DEFINES += -DIMPL_THEBES
ifdef MOZ_DEBUG
DEFINES += -DD3D_DEBUG_INFO
endif
EXPORTS = \
BasicLayers.h \
@ -70,6 +74,21 @@ CPPSRCS = \
ImageLayerOGL.cpp \
CanvasLayerOGL.cpp \
$(NULL)
ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
ifndef WINCE
EXPORTS += LayerManagerD3D9.h
CPPSRCS += \
LayerManagerD3D9.cpp \
ThebesLayerD3D9.cpp \
ContainerLayerD3D9.cpp \
ImageLayerD3D9.cpp \
ColorLayerD3D9.cpp \
CanvasLayerD3D9.cpp \
$(NULL)
endif
endif
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,231 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Corporation code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Vladimir Vukicevic <vladimir@pobox.com>
* Bas Schouten <bschouten@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "CanvasLayerD3D9.h"
#include "gfxImageSurface.h"
#include "gfxWindowsSurface.h"
namespace mozilla {
namespace layers {
CanvasLayerD3D9::~CanvasLayerD3D9()
{
}
void
CanvasLayerD3D9::Initialize(const Data& aData)
{
NS_ASSERTION(mSurface == nsnull, "BasicCanvasLayer::Initialize called twice!");
if (aData.mSurface) {
mSurface = aData.mSurface;
NS_ASSERTION(aData.mGLContext == nsnull,
"CanvasLayer can't have both surface and GLContext");
mNeedsYFlip = PR_FALSE;
} else if (aData.mGLContext) {
mGLContext = aData.mGLContext;
mGLBufferIsPremultiplied = aData.mGLBufferIsPremultiplied;
mNeedsYFlip = PR_TRUE;
} else {
NS_ERROR("CanvasLayer created without mSurface or mGLContext?");
}
mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height);
device()->CreateTexture(mBounds.width, mBounds.height, 1, 0,
D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
getter_AddRefs(mTexture), NULL);
}
void
CanvasLayerD3D9::Updated(const nsIntRect& aRect)
{
if (!mTexture) {
NS_WARNING("CanvasLayerD3D9::Updated called but no texture present!");
return;
}
if (mGLContext) {
// WebGL reads entire surface.
D3DLOCKED_RECT r;
mTexture->LockRect(0, &r, NULL, 0);
PRUint8 *destination;
if (r.Pitch != mBounds.width * 4) {
destination = new PRUint8[mBounds.width * mBounds.height * 4];
} else {
destination = (PRUint8*)r.pBits;
}
// We have to flush to ensure that any buffered GL operations are
// in the framebuffer before we read.
mGLContext->fFlush();
// For simplicity, we read the entire framebuffer for now -- in
// the future we should use aRect, though with WebGL we don't
// have an easy way to generate one.
mGLContext->fReadPixels(0, 0, mBounds.width, mBounds.height,
LOCAL_GL_BGRA, LOCAL_GL_UNSIGNED_INT_8_8_8_8_REV,
destination);
if (r.Pitch != mBounds.width * 4) {
for (int y = 0; y < mBounds.height; y++) {
memcpy((PRUint8*)r.pBits + r.Pitch * y,
destination + mBounds.width * 4 * y,
mBounds.width * 4);
}
delete [] destination;
}
mTexture->UnlockRect(0);
} else if (mSurface) {
RECT r;
r.left = aRect.x;
r.top = aRect.y;
r.right = aRect.XMost();
r.bottom = aRect.YMost();
D3DLOCKED_RECT lockedRect;
mTexture->LockRect(0, &lockedRect, &r, 0);
PRUint8 *startBits;
PRUint32 sourceStride;
nsRefPtr<gfxImageSurface> sourceSurface;
if (mSurface->GetType() == gfxASurface::SurfaceTypeWin32) {
sourceSurface = static_cast<gfxWindowsSurface*>(mSurface.get())->GetImageSurface();
startBits = sourceSurface->Data() + sourceSurface->Stride() * aRect.y +
aRect.x * 4;
sourceStride = sourceSurface->Stride();
} else if (mSurface->GetType() == gfxASurface::SurfaceTypeImage) {
sourceSurface = static_cast<gfxImageSurface*>(sourceSurface.get());
if (sourceSurface->Format() != gfxASurface::ImageFormatARGB32 &&
sourceSurface->Format() != gfxASurface::ImageFormatRGB24)
{
mTexture->UnlockRect(0);
return;
}
startBits = sourceSurface->Data() + sourceSurface->Stride() * aRect.y +
aRect.x * 4;
sourceStride = sourceSurface->Stride();
} else {
sourceSurface = new gfxImageSurface(gfxIntSize(aRect.width, aRect.height),
gfxASurface::ImageFormatARGB32);
nsRefPtr<gfxContext> ctx = new gfxContext(sourceSurface);
ctx->Translate(gfxPoint(-aRect.x, -aRect.y));
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
ctx->SetSource(sourceSurface);
ctx->Paint();
startBits = sourceSurface->Data();
sourceStride = sourceSurface->Stride();
}
for (int y = 0; y < aRect.height; y++) {
memcpy((PRUint8*)lockedRect.pBits + lockedRect.Pitch * y,
startBits + sourceStride * y,
aRect.width * 4);
}
mTexture->UnlockRect(0);
}
}
LayerD3D9::LayerType
CanvasLayerD3D9::GetType()
{
return TYPE_CANVAS;
}
Layer*
CanvasLayerD3D9::GetLayer()
{
return this;
}
void
CanvasLayerD3D9::RenderLayer()
{
float quadTransform[4][4];
/*
* Matrix to transform the <0.0,0.0>, <1.0,1.0> quad to the correct position
* and size. To get pixel perfect mapping we offset the quad half a pixel
* to the top-left. We also flip the Y axis here, note we can only do this
* because we are in CULL_NONE mode!
*
* See: http://msdn.microsoft.com/en-us/library/bb219690%28VS.85%29.aspx
*/
memset(&quadTransform, 0, sizeof(quadTransform));
quadTransform[0][0] = (float)mBounds.width;
if (mNeedsYFlip) {
quadTransform[1][1] = (float)-mBounds.height;
quadTransform[3][1] = (float)mBounds.height - 0.5f;
} else {
quadTransform[1][1] = (float)mBounds.height;
quadTransform[3][1] = -0.5f;
}
quadTransform[2][2] = 1.0f;
quadTransform[3][0] = -0.5f;
quadTransform[3][3] = 1.0f;
device()->SetVertexShaderConstantF(0, &quadTransform[0][0], 4);
device()->SetVertexShaderConstantF(4, &mTransform._11, 4);
float opacity[4];
/*
* We always upload a 4 component float, but the shader will use only the
* first component since it's declared as a 'float'.
*/
opacity[0] = GetOpacity();
device()->SetPixelShaderConstantF(0, opacity, 1);
mD3DManager->SetShaderMode(LayerManagerD3D9::RGBLAYER);
if (!mGLBufferIsPremultiplied) {
device()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
}
device()->SetTexture(0, mTexture);
device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
if (!mGLBufferIsPremultiplied) {
device()->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
}
}
} /* namespace layers */
} /* namespace mozilla */

View File

@ -0,0 +1,90 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Corporation code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Vladimir Vukicevic <vladimir@pobox.com>
* Bas Schouten <bschouten@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef GFX_CANVASLAYEROGL_H
#define GFX_CANVASLAYEROGL_H
#include "LayerManagerD3D9.h"
#include "GLContext.h"
#include "gfxASurface.h"
namespace mozilla {
namespace layers {
class THEBES_API CanvasLayerD3D9 :
public CanvasLayer,
public LayerD3D9
{
public:
CanvasLayerD3D9(LayerManagerD3D9 *aManager)
: CanvasLayer(aManager, NULL),
LayerD3D9(aManager),
mTexture(0),
mGLBufferIsPremultiplied(PR_FALSE),
mNeedsYFlip(PR_FALSE)
{
mImplData = static_cast<LayerD3D9*>(this);
}
~CanvasLayerD3D9();
// CanvasLayer implementation
virtual void Initialize(const Data& aData);
virtual void Updated(const nsIntRect& aRect);
// LayerD3D9 implementation
virtual LayerType GetType();
virtual Layer* GetLayer();
virtual void RenderLayer();
protected:
typedef mozilla::gl::GLContext GLContext;
nsRefPtr<gfxASurface> mSurface;
nsRefPtr<GLContext> mGLContext;
nsRefPtr<IDirect3DTexture9> mTexture;
nsIntRect mBounds;
PRPackedBool mGLBufferIsPremultiplied;
PRPackedBool mNeedsYFlip;
};
} /* layers */
} /* mozilla */
#endif /* GFX_CANVASLAYERD3D9_H */

View File

@ -0,0 +1,91 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Corporation code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Robert O'Callahan <robert@ocallahan.org>
* Bas Schouten <bschouten@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "ColorLayerD3D9.h"
namespace mozilla {
namespace layers {
LayerD3D9::LayerType
ColorLayerD3D9::GetType()
{
return TYPE_COLOR;
}
Layer*
ColorLayerD3D9::GetLayer()
{
return this;
}
void
ColorLayerD3D9::RenderLayer()
{
// XXX we might be able to improve performance by using
// IDirect3DDevice9::Clear
float quadTransform[4][4];
nsIntRect visibleRect = mVisibleRegion.GetBounds();
// Transform the quad to the size of the visible area.
memset(&quadTransform, 0, sizeof(quadTransform));
quadTransform[0][0] = (float)visibleRect.width;
quadTransform[1][1] = (float)visibleRect.height;
quadTransform[2][2] = 1.0f;
quadTransform[3][0] = (float)visibleRect.x;
quadTransform[3][1] = (float)visibleRect.y;
quadTransform[3][3] = 1.0f;
device()->SetVertexShaderConstantF(0, &quadTransform[0][0], 4);
device()->SetVertexShaderConstantF(4, &mTransform._11, 4);
float color[4];
// color is premultiplied, so we need to adjust all channels
color[0] = (float)(mColor.r * GetOpacity());
color[1] = (float)(mColor.g * GetOpacity());
color[2] = (float)(mColor.b * GetOpacity());
color[3] = (float)(mColor.a * GetOpacity());
device()->SetPixelShaderConstantF(0, color, 1);
mD3DManager->SetShaderMode(LayerManagerD3D9::SOLIDCOLORLAYER);
device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
}
} /* layers */
} /* mozilla */

View File

@ -0,0 +1,74 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Corporation code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Robert O'Callahan <robert@ocallahan.org>
* Bas Schouten <bschouten@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef GFX_COLORLAYERD3D9_H
#define GFX_COLORLAYERD3D9_H
#include "LayerManagerD3D9.h"
namespace mozilla {
namespace layers {
class THEBES_API ColorLayerD3D9 : public ColorLayer,
public LayerD3D9
{
public:
ColorLayerD3D9(LayerManagerD3D9 *aManager)
: ColorLayer(aManager, NULL)
, LayerD3D9(aManager)
{
mImplData = static_cast<LayerD3D9*>(this);
}
virtual void SetVisibleRegion(const nsIntRegion& aRegion) { mVisibleRegion = aRegion; }
// LayerD3D9 Implementation
virtual LayerType GetType();
virtual Layer* GetLayer();
virtual void RenderLayer();
protected:
nsIntRegion mVisibleRegion;
};
} /* layers */
} /* mozilla */
#endif /* GFX_COLORLAYERD3D9_H */

View File

@ -0,0 +1,252 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Corporation code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Bas Schouten <bschouten@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "ContainerLayerD3D9.h"
namespace mozilla {
namespace layers {
ContainerLayerD3D9::ContainerLayerD3D9(LayerManagerD3D9 *aManager)
: ContainerLayer(aManager, NULL)
, LayerD3D9(aManager)
{
mImplData = static_cast<LayerD3D9*>(this);
}
const nsIntRect&
ContainerLayerD3D9::GetVisibleRect()
{
return mVisibleRect;
}
void
ContainerLayerD3D9::SetVisibleRegion(const nsIntRegion &aRegion)
{
mVisibleRect = aRegion.GetBounds();
}
void
ContainerLayerD3D9::InsertAfter(Layer* aChild, Layer* aAfter)
{
LayerD3D9 *newChild = static_cast<LayerD3D9*>(aChild->ImplData());
aChild->SetParent(this);
if (!aAfter) {
LayerD3D9 *oldFirstChild = GetFirstChildD3D9();
mFirstChild = newChild->GetLayer();
newChild->SetNextSibling(oldFirstChild);
return;
}
for (LayerD3D9 *child = GetFirstChildD3D9();
child; child = child->GetNextSibling()) {
if (aAfter == child->GetLayer()) {
LayerD3D9 *oldNextSibling = child->GetNextSibling();
child->SetNextSibling(newChild);
child->GetNextSibling()->SetNextSibling(oldNextSibling);
return;
}
}
NS_WARNING("Failed to find aAfter layer!");
}
void
ContainerLayerD3D9::RemoveChild(Layer *aChild)
{
if (GetFirstChild() == aChild) {
mFirstChild = GetFirstChildD3D9()->GetNextSibling() ?
GetFirstChildD3D9()->GetNextSibling()->GetLayer() : nsnull;
return;
}
LayerD3D9 *lastChild = NULL;
for (LayerD3D9 *child = GetFirstChildD3D9(); child;
child = child->GetNextSibling()) {
if (child->GetLayer() == aChild) {
// We're sure this is not our first child. So lastChild != NULL.
lastChild->SetNextSibling(child->GetNextSibling());
child->SetNextSibling(NULL);
child->GetLayer()->SetParent(NULL);
return;
}
lastChild = child;
}
}
LayerD3D9::LayerType
ContainerLayerD3D9::GetType()
{
return TYPE_CONTAINER;
}
Layer*
ContainerLayerD3D9::GetLayer()
{
return this;
}
LayerD3D9*
ContainerLayerD3D9::GetFirstChildD3D9()
{
if (!mFirstChild) {
return nsnull;
}
return static_cast<LayerD3D9*>(mFirstChild->ImplData());
}
void
ContainerLayerD3D9::RenderLayer()
{
float opacity = GetOpacity();
nsRefPtr<IDirect3DSurface9> previousRenderTarget;
nsRefPtr<IDirect3DTexture9> renderTexture;
float previousRenderTargetOffset[4];
float renderTargetOffset[] = { 0, 0, 0, 0 };
float oldViewMatrix[4][4];
PRBool useIntermediate = (opacity != 1.0 || !mTransform.IsIdentity());
if (useIntermediate) {
device()->GetRenderTarget(0, getter_AddRefs(previousRenderTarget));
device()->CreateTexture(mVisibleRect.width, mVisibleRect.height, 1,
D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
D3DPOOL_DEFAULT, getter_AddRefs(renderTexture),
NULL);
nsRefPtr<IDirect3DSurface9> renderSurface;
renderTexture->GetSurfaceLevel(0, getter_AddRefs(renderSurface));
device()->SetRenderTarget(0, renderSurface);
device()->GetVertexShaderConstantF(12, previousRenderTargetOffset, 1);
renderTargetOffset[0] = (float)GetVisibleRect().x;
renderTargetOffset[1] = (float)GetVisibleRect().y;
device()->SetVertexShaderConstantF(12, renderTargetOffset, 1);
float viewMatrix[4][4];
/*
* Matrix to transform to viewport space ( <-1.0, 1.0> topleft,
* <1.0, -1.0> bottomright)
*/
memset(&viewMatrix, 0, sizeof(viewMatrix));
viewMatrix[0][0] = 2.0f / mVisibleRect.width;
viewMatrix[1][1] = -2.0f / mVisibleRect.height;
viewMatrix[2][2] = 1.0f;
viewMatrix[3][0] = -1.0f;
viewMatrix[3][1] = 1.0f;
viewMatrix[3][3] = 1.0f;
device()->GetVertexShaderConstantF(8, &oldViewMatrix[0][0], 4);
device()->SetVertexShaderConstantF(8, &viewMatrix[0][0], 4);
}
/*
* Render this container's contents.
*/
LayerD3D9 *layerToRender = GetFirstChildD3D9();
while (layerToRender) {
const nsIntRect *clipRect = layerToRender->GetLayer()->GetClipRect();
RECT r;
if (clipRect) {
r.left = (LONG)(clipRect->x - renderTargetOffset[0]);
r.top = (LONG)(clipRect->y - renderTargetOffset[1]);
r.right = (LONG)(clipRect->x - renderTargetOffset[0] + clipRect->width);
r.bottom = (LONG)(clipRect->y - renderTargetOffset[1] + clipRect->height);
} else {
if (useIntermediate) {
r.left = 0;
r.top = 0;
} else {
r.left = GetVisibleRect().x;
r.top = GetVisibleRect().y;
}
r.right = r.left + GetVisibleRect().width;
r.bottom = r.top + GetVisibleRect().height;
}
nsRefPtr<IDirect3DSurface9> renderSurface;
device()->GetRenderTarget(0, getter_AddRefs(renderSurface));
D3DSURFACE_DESC desc;
renderSurface->GetDesc(&desc);
r.left = NS_MAX<LONG>(0, r.left);
r.top = NS_MAX<LONG>(0, r.top);
r.bottom = NS_MIN<LONG>(r.bottom, desc.Height);
r.right = NS_MIN<LONG>(r.right, desc.Width);
device()->SetScissorRect(&r);
layerToRender->RenderLayer();
layerToRender = layerToRender->GetNextSibling();
}
if (useIntermediate) {
device()->SetRenderTarget(0, previousRenderTarget);
device()->SetVertexShaderConstantF(12, previousRenderTargetOffset, 1);
device()->SetVertexShaderConstantF(8, &oldViewMatrix[0][0], 4);
float quadTransform[4][4];
/*
* Matrix to transform the <0.0,0.0>, <1.0,1.0> quad to the correct position
* and size. To get pixel perfect mapping we offset the quad half a pixel
* to the top-left.
*
* See: http://msdn.microsoft.com/en-us/library/bb219690%28VS.85%29.aspx
*/
memset(&quadTransform, 0, sizeof(quadTransform));
quadTransform[0][0] = (float)GetVisibleRect().width;
quadTransform[1][1] = (float)GetVisibleRect().height;
quadTransform[2][2] = 1.0f;
quadTransform[3][0] = (float)GetVisibleRect().x - 0.5f;
quadTransform[3][1] = (float)GetVisibleRect().y - 0.5f;
quadTransform[3][3] = 1.0f;
device()->SetVertexShaderConstantF(0, &quadTransform[0][0], 4);
device()->SetVertexShaderConstantF(4, &mTransform._11, 4);
float opacityVector[4];
/*
* We always upload a 4 component float, but the shader will use only the
* first component since it's declared as a 'float'.
*/
opacityVector[0] = opacity;
device()->SetPixelShaderConstantF(0, opacityVector, 1);
mD3DManager->SetShaderMode(LayerManagerD3D9::RGBLAYER);
device()->SetTexture(0, renderTexture);
device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
}
}
} /* layers */
} /* mozilla */

View File

@ -0,0 +1,80 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Corporation code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Bas Schouten <bschouten@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef GFX_CONTAINERLAYERD3D9_H
#define GFX_CONTAINERLAYERD3D9_H
#include "Layers.h"
#include "LayerManagerD3D9.h"
namespace mozilla {
namespace layers {
class ContainerLayerD3D9 : public ContainerLayer,
public LayerD3D9
{
public:
ContainerLayerD3D9(LayerManagerD3D9 *aManager);
const nsIntRect &GetVisibleRect();
/* ContainerLayer implementation */
void SetVisibleRegion(const nsIntRegion& aRegion);
void InsertAfter(Layer* aChild, Layer* aAfter);
void RemoveChild(Layer* aChild);
/* LayerD3D9 implementation */
LayerType GetType();
Layer* GetLayer();
LayerD3D9* GetFirstChildD3D9();
PRBool IsEmpty();
void RenderLayer();
private:
nsIntRect mVisibleRect;
};
} /* layers */
} /* mozilla */
#endif /* GFX_CONTAINERLAYERD3D9_H */

View File

@ -0,0 +1,463 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Corporation code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Bas Schouten <bschouten@mozilla.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "ImageLayerD3D9.h"
#include "gfxImageSurface.h"
#include "yuv_convert.h"
namespace mozilla {
namespace layers {
using mozilla::MutexAutoLock;
ImageContainerD3D9::ImageContainerD3D9(LayerManagerD3D9 *aManager)
: ImageContainer(aManager)
, mActiveImageLock("mozilla.layers.ImageContainerD3D9.mActiveImageLock")
{
}
already_AddRefed<Image>
ImageContainerD3D9::CreateImage(const Image::Format *aFormats,
PRUint32 aNumFormats)
{
if (!aNumFormats) {
return nsnull;
}
nsRefPtr<Image> img;
if (aFormats[0] == Image::PLANAR_YCBCR) {
img = new PlanarYCbCrImageD3D9(static_cast<LayerManagerD3D9*>(mManager));
} else if (aFormats[0] == Image::CAIRO_SURFACE) {
img = new CairoImageD3D9(static_cast<LayerManagerD3D9*>(mManager));
}
return img.forget();
}
void
ImageContainerD3D9::SetCurrentImage(Image *aImage)
{
MutexAutoLock lock(mActiveImageLock);
mActiveImage = aImage;
}
already_AddRefed<Image>
ImageContainerD3D9::GetCurrentImage()
{
MutexAutoLock lock(mActiveImageLock);
nsRefPtr<Image> retval = mActiveImage;
return retval.forget();
}
already_AddRefed<gfxASurface>
ImageContainerD3D9::GetCurrentAsSurface(gfxIntSize *aSize)
{
MutexAutoLock lock(mActiveImageLock);
if (!mActiveImage) {
return nsnull;
}
if (mActiveImage->GetFormat() == Image::PLANAR_YCBCR) {
PlanarYCbCrImageD3D9 *yuvImage =
static_cast<PlanarYCbCrImageD3D9*>(mActiveImage.get());
if (yuvImage->HasData()) {
*aSize = yuvImage->mSize;
}
} else if (mActiveImage->GetFormat() == Image::CAIRO_SURFACE) {
CairoImageD3D9 *cairoImage =
static_cast<CairoImageD3D9*>(mActiveImage.get());
*aSize = cairoImage->mSize;
}
return static_cast<ImageD3D9*>(mActiveImage->GetImplData())->GetAsSurface();
}
gfxIntSize
ImageContainerD3D9::GetCurrentSize()
{
MutexAutoLock lock(mActiveImageLock);
if (!mActiveImage) {
return gfxIntSize(0,0);
}
if (mActiveImage->GetFormat() == Image::PLANAR_YCBCR) {
PlanarYCbCrImageD3D9 *yuvImage =
static_cast<PlanarYCbCrImageD3D9*>(mActiveImage.get());
if (!yuvImage->HasData()) {
return gfxIntSize(0,0);
}
return yuvImage->mSize;
} else if (mActiveImage->GetFormat() == Image::CAIRO_SURFACE) {
CairoImageD3D9 *cairoImage =
static_cast<CairoImageD3D9*>(mActiveImage.get());
return cairoImage->mSize;
}
return gfxIntSize(0,0);
}
LayerD3D9::LayerType
ImageLayerD3D9::GetType()
{
return TYPE_IMAGE;
}
Layer*
ImageLayerD3D9::GetLayer()
{
return this;
}
void
ImageLayerD3D9::RenderLayer()
{
if (!GetContainer()) {
return;
}
nsRefPtr<Image> image = GetContainer()->GetCurrentImage();
if (image->GetFormat() == Image::PLANAR_YCBCR) {
PlanarYCbCrImageD3D9 *yuvImage =
static_cast<PlanarYCbCrImageD3D9*>(image.get());
if (!yuvImage->HasData()) {
return;
}
yuvImage->AllocateTextures();
float quadTransform[4][4];
/*
* Matrix to transform the <0.0,0.0>, <1.0,1.0> quad to the correct position
* and size. To get pixel perfect mapping we extend the quad half a pixel
* beyond all edges.
*/
memset(&quadTransform, 0, sizeof(quadTransform));
quadTransform[0][0] = (float)yuvImage->mSize.width + 0.5f;
quadTransform[1][1] = (float)yuvImage->mSize.height + 0.5f;
quadTransform[2][2] = 1.0f;
quadTransform[3][3] = 1.0f;
device()->SetVertexShaderConstantF(0, &quadTransform[0][0], 4);
device()->SetVertexShaderConstantF(4, &mTransform._11, 4);
float opacity[4];
/*
* We always upload a 4 component float, but the shader will
* only use the the first component since it's declared as a 'float'.
*/
opacity[0] = GetOpacity();
device()->SetPixelShaderConstantF(0, opacity, 1);
mD3DManager->SetShaderMode(LayerManagerD3D9::YCBCRLAYER);
device()->SetTexture(0, yuvImage->mYTexture);
device()->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
device()->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
device()->SetTexture(1, yuvImage->mCbTexture);
device()->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
device()->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
device()->SetTexture(2, yuvImage->mCrTexture);
device()->SetSamplerState(2, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
device()->SetSamplerState(2, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
} else if (image->GetFormat() == Image::CAIRO_SURFACE) {
CairoImageD3D9 *cairoImage =
static_cast<CairoImageD3D9*>(image.get());
float quadTransform[4][4];
/*
* Matrix to transform the <0.0,0.0>, <1.0,1.0> quad to the correct position
* and size. To get pixel perfect mapping we extend the quad half a pixel
* beyond all edges.
*/
memset(&quadTransform, 0, sizeof(quadTransform));
quadTransform[0][0] = (float)cairoImage->mSize.width + 0.5f;
quadTransform[1][1] = (float)cairoImage->mSize.height + 0.5f;
quadTransform[2][2] = 1.0f;
quadTransform[3][3] = 1.0f;
device()->SetVertexShaderConstantF(0, &quadTransform[0][0], 4);
device()->SetVertexShaderConstantF(4, &mTransform._11, 4);
float opacity[4];
/*
* We always upload a 4 component float, but the shader will
* only use the the first component since it's declared as a 'float'.
*/
opacity[0] = GetOpacity();
device()->SetPixelShaderConstantF(0, opacity, 1);
mD3DManager->SetShaderMode(LayerManagerD3D9::RGBLAYER);
device()->SetTexture(0, cairoImage->mTexture);
device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
}
}
PlanarYCbCrImageD3D9::PlanarYCbCrImageD3D9(mozilla::layers::LayerManagerD3D9* aManager)
: PlanarYCbCrImage(static_cast<ImageD3D9*>(this))
, mManager(aManager)
, mHasData(PR_FALSE)
{
}
void
PlanarYCbCrImageD3D9::SetData(const PlanarYCbCrImage::Data &aData)
{
// For now, we copy the data
int width_shift = 0;
int height_shift = 0;
if (aData.mYSize.width == aData.mCbCrSize.width &&
aData.mYSize.height == aData.mCbCrSize.height) {
// YV24 format
width_shift = 0;
height_shift = 0;
} else if (aData.mYSize.width / 2 == aData.mCbCrSize.width &&
aData.mYSize.height == aData.mCbCrSize.height) {
// YV16 format
width_shift = 1;
height_shift = 0;
} else if (aData.mYSize.width / 2 == aData.mCbCrSize.width &&
aData.mYSize.height / 2 == aData.mCbCrSize.height ) {
// YV12 format
width_shift = 1;
height_shift = 1;
} else {
NS_ERROR("YCbCr format not supported");
}
mData = aData;
mData.mCbCrStride = mData.mCbCrSize.width = aData.mPicSize.width >> width_shift;
mData.mCbCrSize.height = aData.mPicSize.height >> height_shift;
mData.mYSize = aData.mPicSize;
mData.mYStride = mData.mYSize.width;
mBuffer = new PRUint8[mData.mCbCrStride * mData.mCbCrSize.height * 2 +
mData.mYStride * mData.mYSize.height];
mData.mYChannel = mBuffer;
mData.mCbChannel = mData.mYChannel + mData.mYStride * mData.mYSize.height;
mData.mCrChannel = mData.mCbChannel + mData.mCbCrStride * mData.mCbCrSize.height;
mData.mCrChannel = new PRUint8[mData.mCbCrStride * mData.mCbCrSize.height];
int cbcr_x = aData.mPicX >> width_shift;
int cbcr_y = aData.mPicY >> height_shift;
for (int i = 0; i < mData.mYSize.height; i++) {
memcpy(mData.mYChannel + i * mData.mYStride,
aData.mYChannel + ((aData.mPicY + i) * aData.mYStride) + aData.mPicX,
mData.mYStride);
}
for (int i = 0; i < mData.mCbCrSize.height; i++) {
memcpy(mData.mCbChannel + i * mData.mCbCrStride,
aData.mCbChannel + ((cbcr_y + i) * aData.mCbCrStride) + cbcr_x,
mData.mCbCrStride);
}
for (int i = 0; i < mData.mCbCrSize.height; i++) {
memcpy(mData.mCrChannel + i * mData.mCbCrStride,
aData.mCrChannel + ((cbcr_y + i) * aData.mCbCrStride) + cbcr_x,
mData.mCbCrStride);
}
// Fix picture rect to be correct
mData.mPicX = mData.mPicY = 0;
mSize = aData.mPicSize;
mHasData = PR_TRUE;
}
void
PlanarYCbCrImageD3D9::AllocateTextures()
{
D3DLOCKED_RECT lockrect;
PRUint8* src;
PRUint8* dest;
//XXX: ensure correct usage flags
mManager->device()->CreateTexture(mData.mYSize.width, mData.mYSize.height,
1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
getter_AddRefs(mYTexture), NULL);
/* lock the entire texture */
mYTexture->LockRect(0, &lockrect, NULL, 0);
src = mData.mYChannel;
//FIX cast
dest = (PRUint8*)lockrect.pBits;
// copy over data
for (int h=0; h<mData.mYSize.height; h++) {
memcpy(dest, src, mData.mYSize.width);
dest += lockrect.Pitch;
src += mData.mYStride;
}
mYTexture->UnlockRect(0);
//XXX: ensure correct usage flags
mManager->device()->CreateTexture(mData.mCbCrSize.width, mData.mCbCrSize.height,
1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
getter_AddRefs(mCbTexture), NULL);
/* lock the entire texture */
mCbTexture->LockRect(0, &lockrect, NULL, 0);
src = mData.mCbChannel;
//FIX cast
dest = (PRUint8*)lockrect.pBits;
// copy over data
for (int h=0; h<mData.mCbCrSize.height; h++) {
memcpy(dest, src, mData.mCbCrSize.width);
dest += lockrect.Pitch;
src += mData.mCbCrStride;
}
mCbTexture->UnlockRect(0);
//XXX: ensure correct usage flags
mManager->device()->CreateTexture(mData.mCbCrSize.width, mData.mCbCrSize.height,
1, 0, D3DFMT_L8, D3DPOOL_MANAGED,
getter_AddRefs(mCrTexture), NULL);
/* lock the entire texture */
mCrTexture->LockRect(0, &lockrect, NULL, 0);
src = mData.mCrChannel;
//FIX cast
dest = (PRUint8*)lockrect.pBits;
// copy over data
for (int h=0; h<mData.mCbCrSize.height; h++) {
memcpy(dest, src, mData.mCbCrSize.width);
dest += lockrect.Pitch;
src += mData.mCbCrStride;
}
mCrTexture->UnlockRect(0);
}
void
PlanarYCbCrImageD3D9::FreeTextures()
{
}
already_AddRefed<gfxASurface>
PlanarYCbCrImageD3D9::GetAsSurface()
{
nsRefPtr<gfxImageSurface> imageSurface =
new gfxImageSurface(mSize, gfxASurface::ImageFormatRGB24);
// Convert from YCbCr to RGB now
gfx::ConvertYCbCrToRGB32(mData.mYChannel,
mData.mCbChannel,
mData.mCrChannel,
imageSurface->Data(),
0,
0,
mSize.width,
mSize.height,
mData.mYStride,
mData.mCbCrStride,
imageSurface->Stride(),
gfx::YV12);
return imageSurface.forget().get();
}
CairoImageD3D9::~CairoImageD3D9()
{
}
void
CairoImageD3D9::SetData(const CairoImage::Data &aData)
{
mSize = aData.mSize;
nsRefPtr<gfxImageSurface> imageSurface =
new gfxImageSurface(aData.mSize, gfxASurface::ImageFormatARGB32);
nsRefPtr<gfxContext> context = new gfxContext(imageSurface);
context->SetSource(aData.mSurface);
context->Paint();
//XXX: make sure we're using the correct usage flags
mManager->device()->CreateTexture(aData.mSize.width, aData.mSize.height,
1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED,
getter_AddRefs(mTexture), NULL);
D3DLOCKED_RECT lockrect;
/* lock the entire texture */
mTexture->LockRect(0, &lockrect, NULL, 0);
PRUint8* src = imageSurface->Data();
//FIX cast
PRUint8* dest = (PRUint8*)lockrect.pBits;
// copy over data. If we don't need to do any swaping we can
// use memcpy
for (int i=0; i<aData.mSize.width*aData.mSize.height; i++) {
dest[0] = src[0];
dest[1] = src[1];
dest[2] = src[2];
dest[3] = src[3];
dest += 4;
src += 4;
}
mTexture->UnlockRect(0);
}
already_AddRefed<gfxASurface>
CairoImageD3D9::GetAsSurface()
{
return nsnull;
}
} /* layers */
} /* mozilla */

View File

@ -0,0 +1,155 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Corporation code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Bas Schouten <bschouten@mozilla.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef GFX_IMAGELAYERD3D9_H
#define GFX_IMAGELAYERD3D9_H
#include "LayerManagerD3D9.h"
#include "ImageLayers.h"
#include "mozilla/Mutex.h"
namespace mozilla {
namespace layers {
class THEBES_API ImageContainerD3D9 : public ImageContainer
{
public:
ImageContainerD3D9(LayerManagerD3D9 *aManager);
virtual ~ImageContainerD3D9() {}
virtual already_AddRefed<Image> CreateImage(const Image::Format* aFormats,
PRUint32 aNumFormats);
virtual void SetCurrentImage(Image* aImage);
virtual already_AddRefed<Image> GetCurrentImage();
virtual already_AddRefed<gfxASurface> GetCurrentAsSurface(gfxIntSize* aSize);
virtual gfxIntSize GetCurrentSize();
private:
typedef mozilla::Mutex Mutex;
nsRefPtr<Image> mActiveImage;
Mutex mActiveImageLock;
};
class THEBES_API ImageLayerD3D9 : public ImageLayer,
public LayerD3D9
{
public:
ImageLayerD3D9(LayerManagerD3D9 *aManager)
: ImageLayer(aManager, NULL)
, LayerD3D9(aManager)
{
mImplData = static_cast<LayerD3D9*>(this);
}
// LayerD3D9 Implementation
virtual LayerType GetType();
virtual Layer* GetLayer();
virtual void RenderLayer();
};
class THEBES_API ImageD3D9
{
public:
virtual already_AddRefed<gfxASurface> GetAsSurface() = 0;
};
class THEBES_API PlanarYCbCrImageD3D9 : public PlanarYCbCrImage,
public ImageD3D9
{
public:
PlanarYCbCrImageD3D9(LayerManagerD3D9 *aManager);
virtual void SetData(const Data &aData);
/*
* Upload the data from out mData into our textures. For now we use this to
* make sure the textures are created and filled on the main thread.
*/
void AllocateTextures();
/*
* XXX
* Free the textures, we call this from the main thread when we're done
* drawing this frame. We cannot free this from the constructor since it may
* be destroyed off the main-thread and might not be able to properly clean
* up its textures
*/
void FreeTextures();
PRBool HasData() { return mHasData; }
virtual already_AddRefed<gfxASurface> GetAsSurface();
nsAutoArrayPtr<PRUint8> mBuffer;
LayerManagerD3D9 *mManager;
Data mData;
gfxIntSize mSize;
nsRefPtr<IDirect3DTexture9> mYTexture;
nsRefPtr<IDirect3DTexture9> mCrTexture;
nsRefPtr<IDirect3DTexture9> mCbTexture;
PRPackedBool mHasData;
};
class THEBES_API CairoImageD3D9 : public CairoImage,
public ImageD3D9
{
public:
CairoImageD3D9(LayerManagerD3D9 *aManager)
: CairoImage(static_cast<ImageD3D9*>(this))
, mManager(aManager)
{ }
~CairoImageD3D9();
virtual void SetData(const Data &aData);
virtual already_AddRefed<gfxASurface> GetAsSurface();
nsRefPtr<IDirect3DTexture9> mTexture;
gfxIntSize mSize;
LayerManagerD3D9 *mManager;
};
} /* layers */
} /* mozilla */
#endif /* GFX_IMAGELAYERD3D9_H */

View File

@ -0,0 +1,578 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Corporation code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Bas Schouten <bschouten@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "LayerManagerD3D9.h"
#include "ThebesLayerD3D9.h"
#include "ContainerLayerD3D9.h"
#include "ImageLayerD3D9.h"
#include "ColorLayerD3D9.h"
#include "CanvasLayerD3D9.h"
#include "LayerManagerD3D9Shaders.h"
#include "nsIServiceManager.h"
#include "nsIConsoleService.h"
#include "nsPrintfCString.h"
namespace mozilla {
namespace layers {
struct vertex {
float x, y;
};
IDirect3D9 *LayerManagerD3D9::mD3D9 = NULL;
typedef IDirect3D9* (WINAPI*Direct3DCreate9Func)(
UINT SDKVersion
);
LayerManagerD3D9::LayerManagerD3D9(nsIWidget *aWidget)
{
mWidget = aWidget;
mCurrentCallbackInfo.Callback = NULL;
mCurrentCallbackInfo.CallbackData = NULL;
}
LayerManagerD3D9::~LayerManagerD3D9()
{
}
#define HAS_CAP(a, b) (((a) & (b)) == (b))
#define LACKS_CAP(a, b) !(((a) & (b)) == (b))
PRBool
LayerManagerD3D9::Initialize()
{
if (!mD3D9) {
Direct3DCreate9Func d3d9create = (Direct3DCreate9Func)
GetProcAddress(LoadLibraryW(L"d3d9.dll"), "Direct3DCreate9");
if (!d3d9create) {
return PR_FALSE;
}
mD3D9 = d3d9create(D3D_SDK_VERSION);
if (!mD3D9) {
return PR_FALSE;
}
}
D3DPRESENT_PARAMETERS pp;
memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS));
pp.BackBufferFormat = D3DFMT_A8R8G8B8;
pp.SwapEffect = D3DSWAPEFFECT_COPY;
pp.Windowed = TRUE;
pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
pp.hDeviceWindow = (HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW);
HRESULT hr = mD3D9->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
NULL,
D3DCREATE_FPU_PRESERVE |
D3DCREATE_MULTITHREADED |
D3DCREATE_MIXED_VERTEXPROCESSING,
&pp,
getter_AddRefs(mDevice));
if (FAILED(hr)) {
return PR_FALSE;
}
if (!VerifyCaps()) {
return PR_FALSE;
}
hr = mDevice->CreateVertexShader((DWORD*)LayerQuadVS,
getter_AddRefs(mLayerVS));
if (FAILED(hr)) {
return PR_FALSE;
}
hr = mDevice->CreatePixelShader((DWORD*)RGBShaderPS,
getter_AddRefs(mRGBPS));
if (FAILED(hr)) {
return PR_FALSE;
}
hr = mDevice->CreatePixelShader((DWORD*)YCbCrShaderPS,
getter_AddRefs(mYCbCrPS));
if (FAILED(hr)) {
return PR_FALSE;
}
hr = mDevice->CreatePixelShader((DWORD*)SolidColorShaderPS,
getter_AddRefs(mSolidColorPS));
if (FAILED(hr)) {
return PR_FALSE;
}
hr = mDevice->CreateVertexBuffer(sizeof(vertex) * 4,
0,
0,
D3DPOOL_MANAGED,
getter_AddRefs(mVB),
NULL);
if (FAILED(hr)) {
return PR_FALSE;
}
vertex *vertices;
hr = mVB->Lock(0, 0, (void**)&vertices, 0);
if (FAILED(hr)) {
return PR_FALSE;
}
vertices[0].x = vertices[0].y = 0;
vertices[1].x = 1; vertices[1].y = 0;
vertices[2].x = 0; vertices[2].y = 1;
vertices[3].x = 1; vertices[3].y = 1;
mVB->Unlock();
hr = mDevice->SetStreamSource(0, mVB, 0, sizeof(vertex));
if (FAILED(hr)) {
return PR_FALSE;
}
D3DVERTEXELEMENT9 elements[] = {
{ 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT,
D3DDECLUSAGE_POSITION, 0 },
D3DDECL_END()
};
mDevice->CreateVertexDeclaration(elements, getter_AddRefs(mVD));
SetupRenderState();
nsCOMPtr<nsIConsoleService>
console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
D3DADAPTER_IDENTIFIER9 identifier;
mD3D9->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &identifier);
if (console) {
nsString msg;
msg +=
NS_LITERAL_STRING("Direct3D 9 LayerManager Initialized Succesfully.\nDriver: ");
msg += NS_ConvertUTF8toUTF16(
nsDependentCString((const char*)identifier.Driver));
msg += NS_LITERAL_STRING("\nDescription: ");
msg += NS_ConvertUTF8toUTF16(
nsDependentCString((const char*)identifier.Description));
msg += NS_LITERAL_STRING("\nVersion: ");
msg += NS_ConvertUTF8toUTF16(
nsPrintfCString("%d.%d.%d.%d",
HIWORD(identifier.DriverVersion.HighPart),
LOWORD(identifier.DriverVersion.HighPart),
HIWORD(identifier.DriverVersion.LowPart),
LOWORD(identifier.DriverVersion.LowPart)));
console->LogStringMessage(msg.get());
}
return PR_TRUE;
}
void
LayerManagerD3D9::SetClippingRegion(const nsIntRegion &aClippingRegion)
{
mClippingRegion = aClippingRegion;
}
void
LayerManagerD3D9::BeginTransaction()
{
}
void
LayerManagerD3D9::BeginTransactionWithTarget(gfxContext *aTarget)
{
mTarget = aTarget;
}
void
LayerManagerD3D9::EndConstruction()
{
}
void
LayerManagerD3D9::EndTransaction(DrawThebesLayerCallback aCallback,
void* aCallbackData)
{
mCurrentCallbackInfo.Callback = aCallback;
mCurrentCallbackInfo.CallbackData = aCallbackData;
Render();
/* Clean this out for sanity */
mCurrentCallbackInfo.Callback = NULL;
mCurrentCallbackInfo.CallbackData = NULL;
}
void
LayerManagerD3D9::SetRoot(Layer *aLayer)
{
mRootLayer = static_cast<LayerD3D9*>(aLayer->ImplData());
}
already_AddRefed<ThebesLayer>
LayerManagerD3D9::CreateThebesLayer()
{
nsRefPtr<ThebesLayer> layer = new ThebesLayerD3D9(this);
return layer.forget();
}
already_AddRefed<ContainerLayer>
LayerManagerD3D9::CreateContainerLayer()
{
nsRefPtr<ContainerLayer> layer = new ContainerLayerD3D9(this);
return layer.forget();
}
already_AddRefed<ImageLayer>
LayerManagerD3D9::CreateImageLayer()
{
nsRefPtr<ImageLayer> layer = new ImageLayerD3D9(this);
return layer.forget();
}
already_AddRefed<ColorLayer>
LayerManagerD3D9::CreateColorLayer()
{
nsRefPtr<ColorLayer> layer = new ColorLayerD3D9(this);
return layer.forget();
}
already_AddRefed<CanvasLayer>
LayerManagerD3D9::CreateCanvasLayer()
{
nsRefPtr<CanvasLayer> layer = new CanvasLayerD3D9(this);
return layer.forget();
}
already_AddRefed<ImageContainer>
LayerManagerD3D9::CreateImageContainer()
{
nsRefPtr<ImageContainer> container = new ImageContainerD3D9(this);
return container.forget();
}
void
LayerManagerD3D9::SetShaderMode(ShaderMode aMode)
{
switch (aMode) {
case RGBLAYER:
mDevice->SetVertexShader(mLayerVS);
mDevice->SetPixelShader(mRGBPS);
break;
case YCBCRLAYER:
mDevice->SetVertexShader(mLayerVS);
mDevice->SetPixelShader(mYCbCrPS);
break;
case SOLIDCOLORLAYER:
mDevice->SetVertexShader(mLayerVS);
mDevice->SetPixelShader(mSolidColorPS);
break;
}
}
void
LayerManagerD3D9::Render()
{
if (!SetupBackBuffer()) {
return;
}
SetupPipeline();
nsIntRect rect;
mWidget->GetBounds(rect);
mDevice->Clear(0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0, 0);
mDevice->BeginScene();
if (mRootLayer) {
const nsIntRect *clipRect = mRootLayer->GetLayer()->GetClipRect();
RECT r;
if (clipRect) {
r.left = (LONG)clipRect->x;
r.top = (LONG)clipRect->y;
r.right = (LONG)(clipRect->x + clipRect->width);
r.bottom = (LONG)(clipRect->y + clipRect->height);
} else {
r.left = r.top = 0;
r.right = rect.width;
r.bottom = rect.height;
}
mDevice->SetScissorRect(&r);
mRootLayer->RenderLayer();
}
mDevice->EndScene();
if (!mTarget) {
const nsIntRect *r;
for (nsIntRegionRectIterator iter(mClippingRegion);
(r = iter.Next()) != nsnull;) {
RECT rect;
rect.left = r->x;
rect.top = r->y;
rect.right = r->XMost();
rect.bottom = r->YMost();
mDevice->Present(&rect, &rect, NULL, NULL);
}
} else {
PaintToTarget();
}
}
void
LayerManagerD3D9::SetupPipeline()
{
nsIntRect rect;
mWidget->GetBounds(rect);
float viewMatrix[4][4];
/*
* Matrix to transform to viewport space ( <-1.0, 1.0> topleft,
* <1.0, -1.0> bottomright)
*/
memset(&viewMatrix, 0, sizeof(viewMatrix));
viewMatrix[0][0] = 2.0f / rect.width;
viewMatrix[1][1] = -2.0f / rect.height;
viewMatrix[2][2] = 1.0f;
viewMatrix[3][0] = -1.0f;
viewMatrix[3][1] = 1.0f;
viewMatrix[3][3] = 1.0f;
HRESULT hr = mDevice->SetVertexShaderConstantF(8, &viewMatrix[0][0], 4);
if (FAILED(hr)) {
NS_WARNING("Failed to set projection shader constant!");
}
}
PRBool
LayerManagerD3D9::SetupBackBuffer()
{
nsRefPtr<IDirect3DSurface9> backBuffer;
mDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO,
getter_AddRefs(backBuffer));
D3DSURFACE_DESC desc;
nsIntRect rect;
mWidget->GetBounds(rect);
backBuffer->GetDesc(&desc);
HRESULT hr = mDevice->TestCooperativeLevel();
/* The device is lost or something else is wrong, failure */
if (FAILED(hr) && hr != D3DERR_DEVICENOTRESET) {
return PR_FALSE;
}
/*
* If the backbuffer is the right size, and the device is not lost, we can
* safely render without doing anything.
*/
if ((desc.Width == rect.width && desc.Height == rect.height) &&
SUCCEEDED(hr)) {
return PR_TRUE;
}
/*
* Our device is lost or our backbuffer needs resizing, start by clearing
* out all D3DPOOL_DEFAULT surfaces.
*/
for(unsigned int i = 0; i < mThebesLayers.Length(); i++) {
mThebesLayers[i]->CleanResources();
}
backBuffer = NULL;
D3DPRESENT_PARAMETERS pp;
memset(&pp, 0, sizeof(D3DPRESENT_PARAMETERS));
pp.BackBufferFormat = D3DFMT_A8R8G8B8;
pp.SwapEffect = D3DSWAPEFFECT_COPY;
pp.Windowed = TRUE;
pp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
pp.hDeviceWindow = (HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW);
hr = mDevice->Reset(&pp);
if (FAILED(hr)) {
return PR_FALSE;
}
SetupRenderState();
return PR_TRUE;
}
void
LayerManagerD3D9::PaintToTarget()
{
nsRefPtr<IDirect3DSurface9> backBuff;
nsRefPtr<IDirect3DSurface9> destSurf;
mDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO,
getter_AddRefs(backBuff));
D3DSURFACE_DESC desc;
backBuff->GetDesc(&desc);
mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height,
D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM,
getter_AddRefs(destSurf), NULL);
mDevice->GetRenderTargetData(backBuff, destSurf);
D3DLOCKED_RECT rect;
destSurf->LockRect(&rect, NULL, D3DLOCK_READONLY);
nsRefPtr<gfxImageSurface> imageSurface =
new gfxImageSurface((unsigned char*)rect.pBits,
gfxIntSize(desc.Width, desc.Height),
rect.Pitch,
gfxASurface::ImageFormatARGB32);
mTarget->SetSource(imageSurface);
mTarget->SetOperator(gfxContext::OPERATOR_OVER);
mTarget->Paint();
destSurf->UnlockRect();
}
void
LayerManagerD3D9::SetupRenderState()
{
mDevice->SetStreamSource(0, mVB, 0, sizeof(vertex));
mDevice->SetVertexDeclaration(mVD);
mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
mDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
mDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
mDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
mDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
mDevice->SetSamplerState(2, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
mDevice->SetSamplerState(2, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
}
PRBool
LayerManagerD3D9::VerifyCaps()
{
D3DCAPS9 caps;
HRESULT hr = mDevice->GetDeviceCaps(&caps);
if (FAILED(hr)) {
return PR_FALSE;
}
if (LACKS_CAP(caps.DevCaps, D3DDEVCAPS_TEXTUREVIDEOMEMORY)) {
return PR_FALSE;
}
if (LACKS_CAP(caps.PrimitiveMiscCaps, D3DPMISCCAPS_CULLNONE)) {
return PR_FALSE;
}
if (LACKS_CAP(caps.SrcBlendCaps, D3DPBLENDCAPS_ONE) ||
LACKS_CAP(caps.SrcBlendCaps, D3DBLEND_SRCALPHA) ||
LACKS_CAP(caps.DestBlendCaps, D3DPBLENDCAPS_INVSRCALPHA)) {
return PR_FALSE;
}
if (LACKS_CAP(caps.RasterCaps, D3DPRASTERCAPS_SCISSORTEST)) {
return PR_FALSE;
}
if (LACKS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_ALPHA) ||
HAS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_SQUAREONLY) ||
(HAS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_POW2) &&
LACKS_CAP(caps.TextureCaps, D3DPTEXTURECAPS_NONPOW2CONDITIONAL))) {
return PR_FALSE;
}
if (LACKS_CAP(caps.TextureFilterCaps, D3DPTFILTERCAPS_MAGFLINEAR) ||
LACKS_CAP(caps.TextureFilterCaps, D3DPTFILTERCAPS_MINFLINEAR)) {
return PR_FALSE;
}
if (LACKS_CAP(caps.TextureAddressCaps, D3DPTADDRESSCAPS_CLAMP)) {
return PR_FALSE;
}
if (caps.MaxTextureHeight < 4096 ||
caps.MaxTextureWidth < 4096) {
return PR_FALSE;
}
if ((caps.PixelShaderVersion & 0xffff) < 0x200 ||
(caps.VertexShaderVersion & 0xffff) < 0x200) {
return PR_FALSE;
}
return PR_TRUE;
}
LayerD3D9::LayerD3D9(LayerManagerD3D9 *aManager)
: mD3DManager(aManager)
, mNextSibling(NULL)
{
}
LayerD3D9*
LayerD3D9::GetNextSibling()
{
return mNextSibling;
}
void
LayerD3D9::SetNextSibling(LayerD3D9 *aNextSibling)
{
mNextSibling = aNextSibling;
}
} /* namespace layers */
} /* namespace mozilla */

View File

@ -0,0 +1,239 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Corporation code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Bas Schouten <bschouten@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef GFX_LAYERMANAGERD3D9_H
#define GFX_LAYERMANAGERD3D9_H
#include "Layers.h"
#include <windows.h>
#include <d3d9.h>
#include "gfxContext.h"
#include "nsIWidget.h"
namespace mozilla {
namespace layers {
class LayerD3D9;
class ThebesLayerD3D9;
/*
* This is the LayerManager used for Direct3D 9. For now this will render on
* the main thread.
*/
class THEBES_API LayerManagerD3D9 : public LayerManager {
public:
LayerManagerD3D9(nsIWidget *aWidget);
virtual ~LayerManagerD3D9();
/*
* Initializes the layer manager, this is when the layer manager will
* actually access the device and attempt to create the swap chain used
* to draw to the window. If this method fails the device cannot be used.
* This function is not threadsafe.
*
* \return True is initialization was succesful, false when it was not.
*/
PRBool Initialize();
/*
* Sets the clipping region for this layer manager. This is important on
* windows because using OGL we no longer have GDI's native clipping. Therefor
* widget must tell us what part of the screen is being invalidated,
* and we should clip to this.
*
* \param aClippingRegion Region to clip to. Setting an empty region
* will disable clipping.
*/
void SetClippingRegion(const nsIntRegion& aClippingRegion);
/*
* LayerManager implementation.
*/
void BeginTransaction();
void BeginTransactionWithTarget(gfxContext* aTarget);
void EndConstruction();
struct CallbackInfo {
DrawThebesLayerCallback Callback;
void *CallbackData;
};
void EndTransaction(DrawThebesLayerCallback aCallback,
void* aCallbackData);
const CallbackInfo &GetCallbackInfo() { return mCurrentCallbackInfo; }
void SetRoot(Layer* aLayer);
virtual already_AddRefed<ThebesLayer> CreateThebesLayer();
virtual already_AddRefed<ContainerLayer> CreateContainerLayer();
virtual already_AddRefed<ImageLayer> CreateImageLayer();
virtual already_AddRefed<ColorLayer> CreateColorLayer();
virtual already_AddRefed<CanvasLayer> CreateCanvasLayer();
virtual already_AddRefed<ImageContainer> CreateImageContainer();
virtual LayersBackend GetBackendType() { return LAYERS_D3D9; }
/*
* Helper methods.
*/
void SetClippingEnabled(PRBool aEnabled);
IDirect3DDevice9 *device() const { return mDevice; }
enum ShaderMode {
RGBLAYER,
YCBCRLAYER,
SOLIDCOLORLAYER
};
void SetShaderMode(ShaderMode aMode);
nsTArray<ThebesLayerD3D9*> mThebesLayers;
private:
/* Direct3D9 instance */
static IDirect3D9 *mD3D9;
/* Widget associated with this layer manager */
nsIWidget *mWidget;
/*
* Context target, NULL when drawing directly to our swap chain.
*/
nsRefPtr<gfxContext> mTarget;
nsRefPtr<IDirect3DDevice9> mDevice;
/* Vertex shader used for layer quads */
nsRefPtr<IDirect3DVertexShader9> mLayerVS;
/* Pixel shader used for RGB textures */
nsRefPtr<IDirect3DPixelShader9> mRGBPS;
/* Pixel shader used for RGB textures */
nsRefPtr<IDirect3DPixelShader9> mYCbCrPS;
/* Pixel shader used for solid colors */
nsRefPtr<IDirect3DPixelShader9> mSolidColorPS;
/* Vertex buffer containing our basic vertex structure */
nsRefPtr<IDirect3DVertexBuffer9> mVB;
/* Our vertex declaration */
nsRefPtr<IDirect3DVertexDeclaration9> mVD;
/* Current root layer. */
LayerD3D9 *mRootLayer;
/* Callback info for current transaction */
CallbackInfo mCurrentCallbackInfo;
/*
* Region we're clipping our current drawing to.
*/
nsIntRegion mClippingRegion;
/*
* Render the current layer tree to the active target.
*/
void Render();
/*
* Setup the pipeline.
*/
void SetupPipeline();
/*
* Setup the backbuffer.
*
* \return PR_TRUE if setup was succesful
*/
PRBool SetupBackBuffer();
/*
* Setup the render state for the surface.
*/
void SetupRenderState();
/*
* Copies the content of our backbuffer to the set transaction target.
*/
void PaintToTarget();
/*
* Verifies all required device capabilities are present.
*/
PRBool VerifyCaps();
};
/*
* General information and tree management for OGL layers.
*/
class LayerD3D9
{
public:
LayerD3D9(LayerManagerD3D9 *aManager);
enum LayerType { TYPE_THEBES, TYPE_CONTAINER, TYPE_IMAGE, TYPE_COLOR,
TYPE_CANVAS };
virtual LayerType GetType() = 0;
LayerD3D9 *GetNextSibling();
virtual LayerD3D9 *GetFirstChildD3D9() { return nsnull; }
void SetNextSibling(LayerD3D9 *aParent);
void SetFirstChild(LayerD3D9 *aParent);
virtual Layer* GetLayer() = 0;
virtual void RenderLayer() = 0;
IDirect3DDevice9 *device() const { return mD3DManager->device(); }
protected:
LayerManagerD3D9 *mD3DManager;
LayerD3D9 *mNextSibling;
};
} /* layers */
} /* mozilla */
#endif /* GFX_LAYERMANAGERD3D9_H */

View File

@ -0,0 +1,435 @@
#if 0
//
// Generated by Microsoft (R) HLSL Shader Compiler 9.27.952.3022
//
// fxc LayerManagerD3D9Shaders.hlsl /ELayerQuadVS /nologo
// /FhLayerManagerD3D9Shaders.h /VnLayerQuadVS
//
//
// Parameters:
//
// float4x4 mLayerQuadTransform;
// float4x4 mLayerTransform;
// float4x4 mProjection;
// float4 vRenderTargetOffset;
//
//
// Registers:
//
// Name Reg Size
// ------------------- ----- ----
// mLayerQuadTransform c0 4
// mLayerTransform c4 4
// mProjection c8 4
// vRenderTargetOffset c12 1
//
vs_2_0
dcl_position v0
mul r0, v0.y, c1
mad r0, c0, v0.x, r0
mad r0, c2, v0.z, r0
mad r0, c3, v0.w, r0
mul r1, r0.y, c5
mad r1, c4, r0.x, r1
mad r1, c6, r0.z, r1
mad r0, c7, r0.w, r1
add r0, r0, -c12
mul r1, r0.y, c9
mad r1, c8, r0.x, r1
mad r1, c10, r0.z, r1
mad oPos, c11, r0.w, r1
mov oT0.xy, v0
// approximately 14 instruction slots used
#endif
const BYTE LayerQuadVS[] =
{
0, 2, 254, 255, 254, 255,
67, 0, 67, 84, 65, 66,
28, 0, 0, 0, 215, 0,
0, 0, 0, 2, 254, 255,
4, 0, 0, 0, 28, 0,
0, 0, 0, 1, 0, 0,
208, 0, 0, 0, 108, 0,
0, 0, 2, 0, 0, 0,
4, 0, 0, 0, 128, 0,
0, 0, 0, 0, 0, 0,
144, 0, 0, 0, 2, 0,
4, 0, 4, 0, 0, 0,
128, 0, 0, 0, 0, 0,
0, 0, 160, 0, 0, 0,
2, 0, 8, 0, 4, 0,
0, 0, 128, 0, 0, 0,
0, 0, 0, 0, 172, 0,
0, 0, 2, 0, 12, 0,
1, 0, 0, 0, 192, 0,
0, 0, 0, 0, 0, 0,
109, 76, 97, 121, 101, 114,
81, 117, 97, 100, 84, 114,
97, 110, 115, 102, 111, 114,
109, 0, 3, 0, 3, 0,
4, 0, 4, 0, 1, 0,
0, 0, 0, 0, 0, 0,
109, 76, 97, 121, 101, 114,
84, 114, 97, 110, 115, 102,
111, 114, 109, 0, 109, 80,
114, 111, 106, 101, 99, 116,
105, 111, 110, 0, 118, 82,
101, 110, 100, 101, 114, 84,
97, 114, 103, 101, 116, 79,
102, 102, 115, 101, 116, 0,
1, 0, 3, 0, 1, 0,
4, 0, 1, 0, 0, 0,
0, 0, 0, 0, 118, 115,
95, 50, 95, 48, 0, 77,
105, 99, 114, 111, 115, 111,
102, 116, 32, 40, 82, 41,
32, 72, 76, 83, 76, 32,
83, 104, 97, 100, 101, 114,
32, 67, 111, 109, 112, 105,
108, 101, 114, 32, 57, 46,
50, 55, 46, 57, 53, 50,
46, 51, 48, 50, 50, 0,
31, 0, 0, 2, 0, 0,
0, 128, 0, 0, 15, 144,
5, 0, 0, 3, 0, 0,
15, 128, 0, 0, 85, 144,
1, 0, 228, 160, 4, 0,
0, 4, 0, 0, 15, 128,
0, 0, 228, 160, 0, 0,
0, 144, 0, 0, 228, 128,
4, 0, 0, 4, 0, 0,
15, 128, 2, 0, 228, 160,
0, 0, 170, 144, 0, 0,
228, 128, 4, 0, 0, 4,
0, 0, 15, 128, 3, 0,
228, 160, 0, 0, 255, 144,
0, 0, 228, 128, 5, 0,
0, 3, 1, 0, 15, 128,
0, 0, 85, 128, 5, 0,
228, 160, 4, 0, 0, 4,
1, 0, 15, 128, 4, 0,
228, 160, 0, 0, 0, 128,
1, 0, 228, 128, 4, 0,
0, 4, 1, 0, 15, 128,
6, 0, 228, 160, 0, 0,
170, 128, 1, 0, 228, 128,
4, 0, 0, 4, 0, 0,
15, 128, 7, 0, 228, 160,
0, 0, 255, 128, 1, 0,
228, 128, 2, 0, 0, 3,
0, 0, 15, 128, 0, 0,
228, 128, 12, 0, 228, 161,
5, 0, 0, 3, 1, 0,
15, 128, 0, 0, 85, 128,
9, 0, 228, 160, 4, 0,
0, 4, 1, 0, 15, 128,
8, 0, 228, 160, 0, 0,
0, 128, 1, 0, 228, 128,
4, 0, 0, 4, 1, 0,
15, 128, 10, 0, 228, 160,
0, 0, 170, 128, 1, 0,
228, 128, 4, 0, 0, 4,
0, 0, 15, 192, 11, 0,
228, 160, 0, 0, 255, 128,
1, 0, 228, 128, 1, 0,
0, 2, 0, 0, 3, 224,
0, 0, 228, 144, 255, 255,
0, 0
};
#if 0
//
// Generated by Microsoft (R) HLSL Shader Compiler 9.27.952.3022
//
// fxc LayerManagerD3D9Shaders.hlsl /ERGBShader /nologo /Tps_2_0
// /FhLayerManagerD3D9Shaders.h /VnRGBShaderPS
//
//
// Parameters:
//
// float fLayerOpacity;
// sampler2D s2D;
//
//
// Registers:
//
// Name Reg Size
// ------------- ----- ----
// fLayerOpacity c0 1
// s2D s0 1
//
ps_2_0
dcl t0.xy
dcl_2d s0
texld r0, t0, s0
mul r0, r0, c0.x
mov oC0, r0
// approximately 3 instruction slots used (1 texture, 2 arithmetic)
#endif
const BYTE RGBShaderPS[] =
{
0, 2, 255, 255, 254, 255,
45, 0, 67, 84, 65, 66,
28, 0, 0, 0, 127, 0,
0, 0, 0, 2, 255, 255,
2, 0, 0, 0, 28, 0,
0, 0, 0, 1, 0, 0,
120, 0, 0, 0, 68, 0,
0, 0, 2, 0, 0, 0,
1, 0, 0, 0, 84, 0,
0, 0, 0, 0, 0, 0,
100, 0, 0, 0, 3, 0,
0, 0, 1, 0, 0, 0,
104, 0, 0, 0, 0, 0,
0, 0, 102, 76, 97, 121,
101, 114, 79, 112, 97, 99,
105, 116, 121, 0, 171, 171,
0, 0, 3, 0, 1, 0,
1, 0, 1, 0, 0, 0,
0, 0, 0, 0, 115, 50,
68, 0, 4, 0, 12, 0,
1, 0, 1, 0, 1, 0,
0, 0, 0, 0, 0, 0,
112, 115, 95, 50, 95, 48,
0, 77, 105, 99, 114, 111,
115, 111, 102, 116, 32, 40,
82, 41, 32, 72, 76, 83,
76, 32, 83, 104, 97, 100,
101, 114, 32, 67, 111, 109,
112, 105, 108, 101, 114, 32,
57, 46, 50, 55, 46, 57,
53, 50, 46, 51, 48, 50,
50, 0, 31, 0, 0, 2,
0, 0, 0, 128, 0, 0,
3, 176, 31, 0, 0, 2,
0, 0, 0, 144, 0, 8,
15, 160, 66, 0, 0, 3,
0, 0, 15, 128, 0, 0,
228, 176, 0, 8, 228, 160,
5, 0, 0, 3, 0, 0,
15, 128, 0, 0, 228, 128,
0, 0, 0, 160, 1, 0,
0, 2, 0, 8, 15, 128,
0, 0, 228, 128, 255, 255,
0, 0
};
#if 0
//
// Generated by Microsoft (R) HLSL Shader Compiler 9.27.952.3022
//
// fxc LayerManagerD3D9Shaders.hlsl /EYCbCrShader /nologo /Tps_2_0
// /FhLayerManagerD3D9Shaders.h /VnYCbCrShaderPS
//
//
// Parameters:
//
// float fLayerOpacity;
// sampler2D s2DCb;
// sampler2D s2DCr;
// sampler2D s2DY;
//
//
// Registers:
//
// Name Reg Size
// ------------- ----- ----
// fLayerOpacity c0 1
// s2DY s0 1
// s2DCb s1 1
// s2DCr s2 1
//
ps_2_0
def c1, -0.5, -0.0625, 1.16400003, 1.59599996
def c2, 0.813000023, 0.391000003, 2.01799989, 1
dcl t0.xy
dcl_2d s0
dcl_2d s1
dcl_2d s2
texld r0, t0, s2
texld r1, t0, s0
texld r2, t0, s1
add r0.x, r0.x, c1.x
add r0.y, r1.x, c1.y
mul r0.y, r0.y, c1.z
mad r0.z, r0.x, -c2.x, r0.y
mad r1.x, r0.x, c1.w, r0.y
add r0.x, r2.x, c1.x
mad r1.y, r0.x, -c2.y, r0.z
mad r1.z, r0.x, c2.z, r0.y
mov r1.w, c2.w
mul r0, r1, c0.x
mov oC0, r0
// approximately 14 instruction slots used (3 texture, 11 arithmetic)
#endif
const BYTE YCbCrShaderPS[] =
{
0, 2, 255, 255, 254, 255,
68, 0, 67, 84, 65, 66,
28, 0, 0, 0, 219, 0,
0, 0, 0, 2, 255, 255,
4, 0, 0, 0, 28, 0,
0, 0, 0, 1, 0, 0,
212, 0, 0, 0, 108, 0,
0, 0, 2, 0, 0, 0,
1, 0, 0, 0, 124, 0,
0, 0, 0, 0, 0, 0,
140, 0, 0, 0, 3, 0,
1, 0, 1, 0, 0, 0,
148, 0, 0, 0, 0, 0,
0, 0, 164, 0, 0, 0,
3, 0, 2, 0, 1, 0,
0, 0, 172, 0, 0, 0,
0, 0, 0, 0, 188, 0,
0, 0, 3, 0, 0, 0,
1, 0, 0, 0, 196, 0,
0, 0, 0, 0, 0, 0,
102, 76, 97, 121, 101, 114,
79, 112, 97, 99, 105, 116,
121, 0, 171, 171, 0, 0,
3, 0, 1, 0, 1, 0,
1, 0, 0, 0, 0, 0,
0, 0, 115, 50, 68, 67,
98, 0, 171, 171, 4, 0,
12, 0, 1, 0, 1, 0,
1, 0, 0, 0, 0, 0,
0, 0, 115, 50, 68, 67,
114, 0, 171, 171, 4, 0,
12, 0, 1, 0, 1, 0,
1, 0, 0, 0, 0, 0,
0, 0, 115, 50, 68, 89,
0, 171, 171, 171, 4, 0,
12, 0, 1, 0, 1, 0,
1, 0, 0, 0, 0, 0,
0, 0, 112, 115, 95, 50,
95, 48, 0, 77, 105, 99,
114, 111, 115, 111, 102, 116,
32, 40, 82, 41, 32, 72,
76, 83, 76, 32, 83, 104,
97, 100, 101, 114, 32, 67,
111, 109, 112, 105, 108, 101,
114, 32, 57, 46, 50, 55,
46, 57, 53, 50, 46, 51,
48, 50, 50, 0, 81, 0,
0, 5, 1, 0, 15, 160,
0, 0, 0, 191, 0, 0,
128, 189, 244, 253, 148, 63,
186, 73, 204, 63, 81, 0,
0, 5, 2, 0, 15, 160,
197, 32, 80, 63, 39, 49,
200, 62, 233, 38, 1, 64,
0, 0, 128, 63, 31, 0,
0, 2, 0, 0, 0, 128,
0, 0, 3, 176, 31, 0,
0, 2, 0, 0, 0, 144,
0, 8, 15, 160, 31, 0,
0, 2, 0, 0, 0, 144,
1, 8, 15, 160, 31, 0,
0, 2, 0, 0, 0, 144,
2, 8, 15, 160, 66, 0,
0, 3, 0, 0, 15, 128,
0, 0, 228, 176, 2, 8,
228, 160, 66, 0, 0, 3,
1, 0, 15, 128, 0, 0,
228, 176, 0, 8, 228, 160,
66, 0, 0, 3, 2, 0,
15, 128, 0, 0, 228, 176,
1, 8, 228, 160, 2, 0,
0, 3, 0, 0, 1, 128,
0, 0, 0, 128, 1, 0,
0, 160, 2, 0, 0, 3,
0, 0, 2, 128, 1, 0,
0, 128, 1, 0, 85, 160,
5, 0, 0, 3, 0, 0,
2, 128, 0, 0, 85, 128,
1, 0, 170, 160, 4, 0,
0, 4, 0, 0, 4, 128,
0, 0, 0, 128, 2, 0,
0, 161, 0, 0, 85, 128,
4, 0, 0, 4, 1, 0,
1, 128, 0, 0, 0, 128,
1, 0, 255, 160, 0, 0,
85, 128, 2, 0, 0, 3,
0, 0, 1, 128, 2, 0,
0, 128, 1, 0, 0, 160,
4, 0, 0, 4, 1, 0,
2, 128, 0, 0, 0, 128,
2, 0, 85, 161, 0, 0,
170, 128, 4, 0, 0, 4,
1, 0, 4, 128, 0, 0,
0, 128, 2, 0, 170, 160,
0, 0, 85, 128, 1, 0,
0, 2, 1, 0, 8, 128,
2, 0, 255, 160, 5, 0,
0, 3, 0, 0, 15, 128,
1, 0, 228, 128, 0, 0,
0, 160, 1, 0, 0, 2,
0, 8, 15, 128, 0, 0,
228, 128, 255, 255, 0, 0
};
#if 0
//
// Generated by Microsoft (R) HLSL Shader Compiler 9.27.952.3022
//
// fxc LayerManagerD3D9Shaders.hlsl /ESolidColorShader /nologo /Tps_2_0
// /FhLayerManagerD3D9Shaders.h /VnSolidColorShaderPS
//
//
// Parameters:
//
// float4 fLayerColor;
//
//
// Registers:
//
// Name Reg Size
// ------------ ----- ----
// fLayerColor c0 1
//
ps_2_0
mov oC0, c0
// approximately 1 instruction slot used
#endif
const BYTE SolidColorShaderPS[] =
{
0, 2, 255, 255, 254, 255,
34, 0, 67, 84, 65, 66,
28, 0, 0, 0, 83, 0,
0, 0, 0, 2, 255, 255,
1, 0, 0, 0, 28, 0,
0, 0, 0, 1, 0, 0,
76, 0, 0, 0, 48, 0,
0, 0, 2, 0, 0, 0,
1, 0, 0, 0, 60, 0,
0, 0, 0, 0, 0, 0,
102, 76, 97, 121, 101, 114,
67, 111, 108, 111, 114, 0,
1, 0, 3, 0, 1, 0,
4, 0, 1, 0, 0, 0,
0, 0, 0, 0, 112, 115,
95, 50, 95, 48, 0, 77,
105, 99, 114, 111, 115, 111,
102, 116, 32, 40, 82, 41,
32, 72, 76, 83, 76, 32,
83, 104, 97, 100, 101, 114,
32, 67, 111, 109, 112, 105,
108, 101, 114, 32, 57, 46,
50, 55, 46, 57, 53, 50,
46, 51, 48, 50, 50, 0,
1, 0, 0, 2, 0, 8,
15, 128, 0, 0, 228, 160,
255, 255, 0, 0
};

View File

@ -0,0 +1,61 @@
float4x4 mLayerQuadTransform;
float4x4 mLayerTransform;
float4 vRenderTargetOffset;
float4x4 mProjection;
texture tex0;
sampler s2D;
sampler s2DY;
sampler s2DCb;
sampler s2DCr;
float fLayerOpacity;
float4 fLayerColor;
struct VS_INPUT {
float4 vPosition : POSITION;
};
struct VS_OUTPUT {
float4 vPosition : POSITION;
float2 vTexCoords : TEXCOORD0;
};
VS_OUTPUT LayerQuadVS(const VS_INPUT aVertex)
{
VS_OUTPUT outp;
outp.vPosition = aVertex.vPosition;
outp.vPosition = mul(mLayerQuadTransform, outp.vPosition);
outp.vPosition = mul(mLayerTransform, outp.vPosition);
outp.vPosition = outp.vPosition - vRenderTargetOffset;
outp.vPosition = mul(mProjection, outp.vPosition);
outp.vTexCoords = aVertex.vPosition.xy;
return outp;
}
float4 RGBShader(const VS_OUTPUT aVertex) : COLOR
{
return tex2D(s2D, aVertex.vTexCoords) * fLayerOpacity;
}
float4 YCbCrShader(const VS_OUTPUT aVertex) : COLOR
{
float4 yuv;
float4 color;
yuv.r = tex2D(s2DCr, aVertex.vTexCoords).r - 0.5;
yuv.g = tex2D(s2DY, aVertex.vTexCoords).r - 0.0625;
yuv.b = tex2D(s2DCb, aVertex.vTexCoords).r - 0.5;
color.r = yuv.g * 1.164 + yuv.r * 1.596;
color.g = yuv.g * 1.164 - 0.813 * yuv.r - 0.391 * yuv.b;
color.b = yuv.g * 1.164 + yuv.b * 2.018;
color.a = 1.0f;
return color * fLayerOpacity;
}
float4 SolidColorShader(const VS_OUTPUT aVertex) : COLOR
{
return fLayerColor;
}

View File

@ -0,0 +1,216 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Corporation code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Bas Schouten <bschouten@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "ThebesLayerD3D9.h"
#include "gfxPlatform.h"
namespace mozilla {
namespace layers {
ThebesLayerD3D9::ThebesLayerD3D9(LayerManagerD3D9 *aManager)
: ThebesLayer(aManager, NULL)
, LayerD3D9(aManager)
{
mImplData = static_cast<LayerD3D9*>(this);
aManager->mThebesLayers.AppendElement(this);
}
ThebesLayerD3D9::~ThebesLayerD3D9()
{
mD3DManager->mThebesLayers.RemoveElement(this);
}
void
ThebesLayerD3D9::SetVisibleRegion(const nsIntRegion &aRegion)
{
if (aRegion.GetBounds() == mVisibleRect) {
return;
}
mVisibleRect = aRegion.GetBounds();
device()->CreateTexture(mVisibleRect.width, mVisibleRect.height, 1,
D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
D3DPOOL_DEFAULT, getter_AddRefs(mTexture), NULL);
mInvalidatedRect = mVisibleRect;
}
void
ThebesLayerD3D9::InvalidateRegion(const nsIntRegion &aRegion)
{
nsIntRegion invalidatedRegion;
invalidatedRegion.Or(aRegion, mInvalidatedRect);
invalidatedRegion.And(invalidatedRegion, mVisibleRect);
mInvalidatedRect = invalidatedRegion.GetBounds();
}
LayerD3D9::LayerType
ThebesLayerD3D9::GetType()
{
return TYPE_THEBES;
}
const nsIntRect&
ThebesLayerD3D9::GetVisibleRect()
{
return mVisibleRect;
}
void
ThebesLayerD3D9::RenderLayer()
{
if (!mTexture) {
device()->CreateTexture(mVisibleRect.width, mVisibleRect.height, 1,
D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8,
D3DPOOL_DEFAULT, getter_AddRefs(mTexture), NULL);
mInvalidatedRect = mVisibleRect;
}
if (!mInvalidatedRect.IsEmpty()) {
nsIntRegion region = mInvalidatedRect;
gfxASurface::gfxImageFormat imageFormat = gfxASurface::ImageFormatARGB32;;
nsRefPtr<gfxASurface> destinationSurface;
nsRefPtr<gfxContext> context;
destinationSurface =
gfxPlatform::GetPlatform()->
CreateOffscreenSurface(gfxIntSize(mInvalidatedRect.width,
mInvalidatedRect.height),
imageFormat);
context = new gfxContext(destinationSurface);
context->Translate(gfxPoint(-mInvalidatedRect.x, -mInvalidatedRect.y));
LayerManagerD3D9::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo();
cbInfo.Callback(this, context, region, cbInfo.CallbackData);
nsRefPtr<IDirect3DTexture9> tmpTexture;
device()->CreateTexture(mInvalidatedRect.width, mInvalidatedRect.height, 1,
0, D3DFMT_A8R8G8B8,
D3DPOOL_SYSTEMMEM, getter_AddRefs(tmpTexture), NULL);
D3DLOCKED_RECT r;
tmpTexture->LockRect(0, &r, NULL, 0);
nsRefPtr<gfxImageSurface> imgSurface =
new gfxImageSurface((unsigned char *)r.pBits,
gfxIntSize(mInvalidatedRect.width,
mInvalidatedRect.height),
r.Pitch,
imageFormat);
context = new gfxContext(imgSurface);
context->SetSource(destinationSurface);
context->SetOperator(gfxContext::OPERATOR_SOURCE);
context->Paint();
imgSurface = NULL;
tmpTexture->UnlockRect(0);
nsRefPtr<IDirect3DSurface9> srcSurface;
nsRefPtr<IDirect3DSurface9> dstSurface;
mTexture->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
tmpTexture->GetSurfaceLevel(0, getter_AddRefs(srcSurface));
POINT point;
point.x = mInvalidatedRect.x - mVisibleRect.x;
point.y = mInvalidatedRect.y - mVisibleRect.y;
device()->UpdateSurface(srcSurface, NULL, dstSurface, &point);
}
float quadTransform[4][4];
/*
* Matrix to transform the <0.0,0.0>, <1.0,1.0> quad to the correct position
* and size. To get pixel perfect mapping we offset the quad half a pixel
* to the top-left.
*
* See: http://msdn.microsoft.com/en-us/library/bb219690%28VS.85%29.aspx
*/
memset(&quadTransform, 0, sizeof(quadTransform));
quadTransform[0][0] = (float)GetVisibleRect().width;
quadTransform[1][1] = (float)GetVisibleRect().height;
quadTransform[2][2] = 1.0f;
quadTransform[3][0] = (float)GetVisibleRect().x - 0.5f;
quadTransform[3][1] = (float)GetVisibleRect().y - 0.5f;
quadTransform[3][3] = 1.0f;
device()->SetVertexShaderConstantF(0, &quadTransform[0][0], 4);
device()->SetVertexShaderConstantF(4, &mTransform._11, 4);
float opacity[4];
/*
* We always upload a 4 component float, but the shader will use only the
* first component since it's declared as a 'float'.
*/
opacity[0] = GetOpacity();
device()->SetPixelShaderConstantF(0, opacity, 1);
mD3DManager->SetShaderMode(LayerManagerD3D9::RGBLAYER);
device()->SetTexture(0, mTexture);
device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
}
void
ThebesLayerD3D9::CleanResources()
{
mTexture = nsnull;
}
const nsIntRect&
ThebesLayerD3D9::GetInvalidatedRect()
{
return mInvalidatedRect;
}
Layer*
ThebesLayerD3D9::GetLayer()
{
return this;
}
PRBool
ThebesLayerD3D9::IsEmpty()
{
return !mTexture;
}
} /* namespace layers */
} /* namespace mozilla */

View File

@ -0,0 +1,92 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Corporation code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Bas Schouten <bschouten@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef GFX_THEBESLAYERD3D9_H
#define GFX_THEBESLAYERD3D9_H
#include "Layers.h"
#include "LayerManagerD3D9.h"
#include "gfxImageSurface.h"
namespace mozilla {
namespace layers {
class ThebesLayerD3D9 : public ThebesLayer,
public LayerD3D9
{
public:
ThebesLayerD3D9(LayerManagerD3D9 *aManager);
virtual ~ThebesLayerD3D9();
/* Layer implementation */
void SetVisibleRegion(const nsIntRegion& aRegion);
/* ThebesLayer implementation */
void InvalidateRegion(const nsIntRegion& aRegion);
/* LayerD3D9 implementation */
LayerType GetType();
Layer* GetLayer();
virtual PRBool IsEmpty();
virtual void RenderLayer();
virtual void CleanResources();
/* ThebesLayerD3D9 */
const nsIntRect &GetVisibleRect();
const nsIntRect &GetInvalidatedRect();
private:
/*
* Visible rectangle, this is used to know the size and position of the quad
* when doing the rendering of this layer.
*/
nsIntRect mVisibleRect;
/*
* Currently invalidated rectangular area.
*/
nsIntRect mInvalidatedRect;
/*
* D3D9 texture
*/
nsRefPtr<IDirect3DTexture9> mTexture;
};
} /* layers */
} /* mozilla */
#endif /* GFX_THEBESLAYERD3D9_H */