зеркало из https://github.com/mozilla/pjs.git
Bug 546514 - Part 3: Add D3D10 layers code. r=vlad
This commit is contained in:
Родитель
e1aacbdbf4
Коммит
61670604f2
|
@ -0,0 +1,273 @@
|
|||
/* -*- 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 "CanvasLayerD3D10.h"
|
||||
|
||||
#include "gfxImageSurface.h"
|
||||
#include "gfxWindowsSurface.h"
|
||||
#include "gfxWindowsPlatform.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
CanvasLayerD3D10::~CanvasLayerD3D10()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
CanvasLayerD3D10::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;
|
||||
mDataIsPremultiplied = PR_TRUE;
|
||||
} else if (aData.mGLContext) {
|
||||
NS_ASSERTION(aData.mGLContext->IsOffscreen(), "canvas gl context isn't offscreen");
|
||||
mGLContext = aData.mGLContext;
|
||||
mCanvasFramebuffer = mGLContext->GetOffscreenFBO();
|
||||
mDataIsPremultiplied = aData.mGLBufferIsPremultiplied;
|
||||
mNeedsYFlip = PR_TRUE;
|
||||
} else {
|
||||
NS_ERROR("CanvasLayer created without mSurface or mGLContext?");
|
||||
}
|
||||
|
||||
mBounds.SetRect(0, 0, aData.mSize.width, aData.mSize.height);
|
||||
|
||||
if (mSurface && mSurface->GetType() == gfxASurface::SurfaceTypeD2D) {
|
||||
void *data = mSurface->GetData(&gKeyD3D10Texture);
|
||||
if (data) {
|
||||
mTexture = static_cast<ID3D10Texture2D*>(data);
|
||||
mIsD2DTexture = true;
|
||||
device()->CreateShaderResourceView(mTexture, NULL, getter_AddRefs(mSRView));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mIsD2DTexture = false;
|
||||
|
||||
CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, mBounds.width, mBounds.height, 1, 1);
|
||||
desc.Usage = D3D10_USAGE_DYNAMIC;
|
||||
desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
|
||||
|
||||
HRESULT hr = device()->CreateTexture2D(&desc, NULL, getter_AddRefs(mTexture));
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to create texture for CanvasLayer!");
|
||||
return;
|
||||
}
|
||||
device()->CreateShaderResourceView(mTexture, NULL, getter_AddRefs(mSRView));
|
||||
}
|
||||
|
||||
void
|
||||
CanvasLayerD3D10::Updated(const nsIntRect& aRect)
|
||||
{
|
||||
if (mIsD2DTexture) {
|
||||
mSurface->Flush();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mGLContext) {
|
||||
// WebGL reads entire surface.
|
||||
D3D10_MAPPED_TEXTURE2D map;
|
||||
|
||||
HRESULT hr = mTexture->Map(0, D3D10_MAP_WRITE_DISCARD, 0, &map);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to map CanvasLayer texture.");
|
||||
return;
|
||||
}
|
||||
|
||||
PRUint8 *destination;
|
||||
if (map.RowPitch != mBounds.width * 4) {
|
||||
destination = new PRUint8[mBounds.width * mBounds.height * 4];
|
||||
} else {
|
||||
destination = (PRUint8*)map.pData;
|
||||
}
|
||||
|
||||
// We have to flush to ensure that any buffered GL operations are
|
||||
// in the framebuffer before we read.
|
||||
mGLContext->fFlush();
|
||||
|
||||
PRUint32 currentFramebuffer = 0;
|
||||
|
||||
mGLContext->fGetIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, (GLint*)¤tFramebuffer);
|
||||
|
||||
// Make sure that we read pixels from the correct framebuffer, regardless
|
||||
// of what's currently bound.
|
||||
if (currentFramebuffer != mCanvasFramebuffer)
|
||||
mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, mCanvasFramebuffer);
|
||||
|
||||
// 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.
|
||||
nsRefPtr<gfxImageSurface> tmpSurface =
|
||||
new gfxImageSurface(destination,
|
||||
gfxIntSize(mBounds.width, mBounds.height),
|
||||
mBounds.width * 4,
|
||||
gfxASurface::ImageFormatARGB32);
|
||||
mGLContext->ReadPixelsIntoImageSurface(0, 0,
|
||||
mBounds.width, mBounds.height,
|
||||
tmpSurface);
|
||||
tmpSurface = nsnull;
|
||||
|
||||
// Put back the previous framebuffer binding.
|
||||
if (currentFramebuffer != mCanvasFramebuffer)
|
||||
mGLContext->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, currentFramebuffer);
|
||||
|
||||
if (map.RowPitch != mBounds.width * 4) {
|
||||
for (int y = 0; y < mBounds.height; y++) {
|
||||
memcpy((PRUint8*)map.pData + map.RowPitch * y,
|
||||
destination + mBounds.width * 4 * y,
|
||||
mBounds.width * 4);
|
||||
}
|
||||
delete [] destination;
|
||||
}
|
||||
mTexture->Unmap(0);
|
||||
} else if (mSurface) {
|
||||
RECT r;
|
||||
r.left = aRect.x;
|
||||
r.top = aRect.y;
|
||||
r.right = aRect.XMost();
|
||||
r.bottom = aRect.YMost();
|
||||
|
||||
D3D10_MAPPED_TEXTURE2D map;
|
||||
HRESULT hr = mTexture->Map(0, D3D10_MAP_WRITE_DISCARD, 0, &map);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to lock CanvasLayer texture.");
|
||||
return;
|
||||
}
|
||||
|
||||
PRUint8 *startBits;
|
||||
PRUint32 sourceStride;
|
||||
|
||||
nsRefPtr<gfxImageSurface> dstSurface;
|
||||
|
||||
dstSurface = new gfxImageSurface((unsigned char*)map.pData,
|
||||
gfxIntSize(aRect.width, aRect.height),
|
||||
map.RowPitch,
|
||||
gfxASurface::ImageFormatARGB32);
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(dstSurface);
|
||||
ctx->Translate(gfxPoint(-aRect.x, -aRect.y));
|
||||
ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
ctx->SetSource(mSurface);
|
||||
ctx->Paint();
|
||||
|
||||
mTexture->Unmap(0);
|
||||
}
|
||||
}
|
||||
|
||||
Layer*
|
||||
CanvasLayerD3D10::GetLayer()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
void
|
||||
CanvasLayerD3D10::RenderLayer(float aOpacity, const gfx3DMatrix &aTransform)
|
||||
{
|
||||
if (!mTexture) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsIntRect visibleRect = mVisibleRegion.GetBounds();
|
||||
|
||||
gfx3DMatrix transform = mTransform * aTransform;
|
||||
effect()->GetVariableByName("mLayerTransform")->SetRawValue(&transform._11, 0, 64);
|
||||
effect()->GetVariableByName("fLayerOpacity")->AsScalar()->SetFloat(GetOpacity() * aOpacity);
|
||||
|
||||
ID3D10EffectTechnique *technique;
|
||||
|
||||
if (mDataIsPremultiplied) {
|
||||
if (mSurface && mSurface->GetContentType() == gfxASurface::CONTENT_COLOR) {
|
||||
if (mFilter == gfxPattern::FILTER_NEAREST) {
|
||||
technique = effect()->GetTechniqueByName("RenderRGBLayerPremulPoint");
|
||||
} else {
|
||||
technique = effect()->GetTechniqueByName("RenderRGBLayerPremul");
|
||||
}
|
||||
} else {
|
||||
if (mFilter == gfxPattern::FILTER_NEAREST) {
|
||||
technique = effect()->GetTechniqueByName("RenderRGBALayerPremulPoint");
|
||||
} else {
|
||||
technique = effect()->GetTechniqueByName("RenderRGBALayerPremul");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (mFilter == gfxPattern::FILTER_NEAREST) {
|
||||
technique = effect()->GetTechniqueByName("RenderRGBALayerNonPremulPoint");
|
||||
} else {
|
||||
technique = effect()->GetTechniqueByName("RenderRGBALayerNonPremul");
|
||||
}
|
||||
}
|
||||
|
||||
if (mSRView) {
|
||||
effect()->GetVariableByName("tRGB")->AsShaderResource()->SetResource(mSRView);
|
||||
}
|
||||
|
||||
effect()->GetVariableByName("vLayerQuad")->AsVector()->SetFloatVector(
|
||||
ShaderConstantRectD3D10(
|
||||
(float)mBounds.x,
|
||||
(float)mBounds.y,
|
||||
(float)mBounds.width,
|
||||
(float)mBounds.height)
|
||||
);
|
||||
|
||||
if (mNeedsYFlip) {
|
||||
effect()->GetVariableByName("vTextureCoords")->AsVector()->SetFloatVector(
|
||||
ShaderConstantRectD3D10(
|
||||
0,
|
||||
1.0f,
|
||||
1.0f,
|
||||
-1.0f)
|
||||
);
|
||||
}
|
||||
|
||||
technique->GetPassByIndex(0)->Apply(0);
|
||||
device()->Draw(4, 0);
|
||||
|
||||
if (mNeedsYFlip) {
|
||||
effect()->GetVariableByName("vTextureCoords")->AsVector()->
|
||||
SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f));
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace layers */
|
||||
} /* namespace mozilla */
|
|
@ -0,0 +1,93 @@
|
|||
/* -*- 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 "LayerManagerD3D10.h"
|
||||
#include "GLContext.h"
|
||||
#include "gfxASurface.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class THEBES_API CanvasLayerD3D10 : public CanvasLayer,
|
||||
public LayerD3D10
|
||||
{
|
||||
public:
|
||||
CanvasLayerD3D10(LayerManagerD3D10 *aManager)
|
||||
: CanvasLayer(aManager, NULL),
|
||||
LayerD3D10(aManager),
|
||||
mTexture(0),
|
||||
mDataIsPremultiplied(PR_FALSE),
|
||||
mNeedsYFlip(PR_FALSE)
|
||||
{
|
||||
mImplData = static_cast<LayerD3D10*>(this);
|
||||
}
|
||||
|
||||
~CanvasLayerD3D10();
|
||||
|
||||
// CanvasLayer implementation
|
||||
virtual void Initialize(const Data& aData);
|
||||
virtual void Updated(const nsIntRect& aRect);
|
||||
|
||||
// LayerD3D10 implementation
|
||||
virtual Layer* GetLayer();
|
||||
virtual void RenderLayer(float aOpacity, const gfx3DMatrix &aTransform);
|
||||
|
||||
private:
|
||||
typedef mozilla::gl::GLContext GLContext;
|
||||
|
||||
nsRefPtr<gfxASurface> mSurface;
|
||||
nsRefPtr<GLContext> mGLContext;
|
||||
|
||||
PRUint32 mCanvasFramebuffer;
|
||||
|
||||
nsRefPtr<ID3D10Texture2D> mTexture;
|
||||
nsRefPtr<ID3D10ShaderResourceView> mSRView;
|
||||
|
||||
nsIntRect mBounds;
|
||||
|
||||
PRPackedBool mDataIsPremultiplied;
|
||||
PRPackedBool mNeedsYFlip;
|
||||
PRPackedBool mIsD2DTexture;
|
||||
};
|
||||
|
||||
} /* layers */
|
||||
} /* mozilla */
|
||||
#endif /* GFX_CANVASLAYERD3D10_H */
|
|
@ -0,0 +1,93 @@
|
|||
/* -*- 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 "ColorLayerD3D10.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
ColorLayerD3D10::ColorLayerD3D10(LayerManagerD3D10 *aManager)
|
||||
: ColorLayer(aManager, NULL)
|
||||
, LayerD3D10(aManager)
|
||||
{
|
||||
mImplData = static_cast<LayerD3D10*>(this);
|
||||
}
|
||||
|
||||
Layer*
|
||||
ColorLayerD3D10::GetLayer()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
void
|
||||
ColorLayerD3D10::RenderLayer(float aOpacity, const gfx3DMatrix &aTransform)
|
||||
{
|
||||
float color[4];
|
||||
// color is premultiplied, so we need to adjust all channels
|
||||
color[0] = (float)(mColor.r * GetOpacity() * aOpacity);
|
||||
color[1] = (float)(mColor.g * GetOpacity() * aOpacity);
|
||||
color[2] = (float)(mColor.b * GetOpacity() * aOpacity);
|
||||
color[3] = (float)(mColor.a * GetOpacity() * aOpacity);
|
||||
|
||||
gfx3DMatrix transform = mTransform * aTransform;
|
||||
|
||||
effect()->GetVariableByName("mLayerTransform")->SetRawValue(&transform._11, 0, 64);
|
||||
effect()->GetVariableByName("fLayerColor")->AsVector()->SetFloatVector(color);
|
||||
|
||||
ID3D10EffectTechnique *technique;
|
||||
technique = effect()->GetTechniqueByName("RenderSolidColorLayer");
|
||||
|
||||
nsIntRegionRectIterator iter(mVisibleRegion);
|
||||
|
||||
const nsIntRect *iterRect;
|
||||
while ((iterRect = iter.Next())) {
|
||||
effect()->GetVariableByName("vLayerQuad")->AsVector()->SetFloatVector(
|
||||
ShaderConstantRectD3D10(
|
||||
(float)iterRect->x,
|
||||
(float)iterRect->y,
|
||||
(float)iterRect->width,
|
||||
(float)iterRect->height)
|
||||
);
|
||||
|
||||
technique->GetPassByIndex(0)->Apply(0);
|
||||
device()->Draw(4, 0);
|
||||
}
|
||||
}
|
||||
|
||||
} /* layers */
|
||||
} /* mozilla */
|
|
@ -0,0 +1,60 @@
|
|||
/* -*- 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_COLORLAYERD3D10_H
|
||||
#define GFX_COLORLAYERD3D10_H
|
||||
|
||||
#include "Layers.h"
|
||||
#include "LayerManagerD3D10.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class ColorLayerD3D10 : public ColorLayer,
|
||||
public LayerD3D10
|
||||
{
|
||||
public:
|
||||
ColorLayerD3D10(LayerManagerD3D10 *aManager);
|
||||
|
||||
/* LayerD3D10 implementation */
|
||||
Layer* GetLayer();
|
||||
virtual void RenderLayer(float aOpacity, const gfx3DMatrix &aTransform);
|
||||
};
|
||||
|
||||
} /* layers */
|
||||
} /* mozilla */
|
||||
#endif /* GFX_THEBESLAYERD3D10_H */
|
|
@ -0,0 +1,337 @@
|
|||
/* -*- 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 "ContainerLayerD3D10.h"
|
||||
#include "nsAlgorithm.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
ContainerLayerD3D10::ContainerLayerD3D10(LayerManagerD3D10 *aManager)
|
||||
: ContainerLayer(aManager, NULL)
|
||||
, LayerD3D10(aManager)
|
||||
{
|
||||
mImplData = static_cast<LayerD3D10*>(this);
|
||||
}
|
||||
|
||||
ContainerLayerD3D10::~ContainerLayerD3D10()
|
||||
{
|
||||
while (mFirstChild) {
|
||||
RemoveChild(mFirstChild);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ContainerLayerD3D10::InsertAfter(Layer* aChild, Layer* aAfter)
|
||||
{
|
||||
aChild->SetParent(this);
|
||||
if (!aAfter) {
|
||||
Layer *oldFirstChild = GetFirstChild();
|
||||
mFirstChild = aChild;
|
||||
aChild->SetNextSibling(oldFirstChild);
|
||||
aChild->SetPrevSibling(nsnull);
|
||||
if (oldFirstChild) {
|
||||
oldFirstChild->SetPrevSibling(aChild);
|
||||
}
|
||||
NS_ADDREF(aChild);
|
||||
return;
|
||||
}
|
||||
for (Layer *child = GetFirstChild();
|
||||
child; child = child->GetNextSibling()) {
|
||||
if (aAfter == child) {
|
||||
Layer *oldNextSibling = child->GetNextSibling();
|
||||
child->SetNextSibling(aChild);
|
||||
aChild->SetNextSibling(oldNextSibling);
|
||||
if (oldNextSibling) {
|
||||
oldNextSibling->SetPrevSibling(aChild);
|
||||
}
|
||||
aChild->SetPrevSibling(child);
|
||||
NS_ADDREF(aChild);
|
||||
return;
|
||||
}
|
||||
}
|
||||
NS_WARNING("Failed to find aAfter layer!");
|
||||
}
|
||||
|
||||
void
|
||||
ContainerLayerD3D10::RemoveChild(Layer *aChild)
|
||||
{
|
||||
if (GetFirstChild() == aChild) {
|
||||
mFirstChild = GetFirstChild()->GetNextSibling();
|
||||
if (mFirstChild) {
|
||||
mFirstChild->SetPrevSibling(nsnull);
|
||||
}
|
||||
aChild->SetNextSibling(nsnull);
|
||||
aChild->SetPrevSibling(nsnull);
|
||||
aChild->SetParent(nsnull);
|
||||
NS_RELEASE(aChild);
|
||||
return;
|
||||
}
|
||||
Layer *lastChild = nsnull;
|
||||
for (Layer *child = GetFirstChild(); child;
|
||||
child = child->GetNextSibling()) {
|
||||
if (child == aChild) {
|
||||
// We're sure this is not our first child. So lastChild != NULL.
|
||||
lastChild->SetNextSibling(child->GetNextSibling());
|
||||
if (child->GetNextSibling()) {
|
||||
child->GetNextSibling()->SetPrevSibling(lastChild);
|
||||
}
|
||||
child->SetNextSibling(nsnull);
|
||||
child->SetPrevSibling(nsnull);
|
||||
child->SetParent(nsnull);
|
||||
NS_RELEASE(aChild);
|
||||
return;
|
||||
}
|
||||
lastChild = child;
|
||||
}
|
||||
}
|
||||
|
||||
Layer*
|
||||
ContainerLayerD3D10::GetLayer()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
LayerD3D10*
|
||||
ContainerLayerD3D10::GetFirstChildD3D10()
|
||||
{
|
||||
if (!mFirstChild) {
|
||||
return nsnull;
|
||||
}
|
||||
return static_cast<LayerD3D10*>(mFirstChild->ImplData());
|
||||
}
|
||||
|
||||
void
|
||||
ContainerLayerD3D10::RenderLayer(float aOpacity, const gfx3DMatrix &aTransform)
|
||||
{
|
||||
float renderTargetOffset[] = { 0, 0 };
|
||||
|
||||
nsIntRect visibleRect = mVisibleRegion.GetBounds();
|
||||
float opacity = GetOpacity() * aOpacity;
|
||||
gfx3DMatrix transform = mTransform * aTransform;
|
||||
PRBool useIntermediate = ShouldUseIntermediate(aOpacity, transform);
|
||||
|
||||
nsRefPtr<ID3D10RenderTargetView> previousRTView;
|
||||
nsRefPtr<ID3D10Texture2D> renderTexture;
|
||||
nsRefPtr<ID3D10RenderTargetView> rtView;
|
||||
float previousRenderTargetOffset[2];
|
||||
nsIntSize previousViewportSize;
|
||||
|
||||
gfx3DMatrix oldViewMatrix;
|
||||
|
||||
if (useIntermediate) {
|
||||
device()->OMGetRenderTargets(1, getter_AddRefs(previousRTView), NULL);
|
||||
|
||||
D3D10_TEXTURE2D_DESC desc;
|
||||
memset(&desc, 0, sizeof(D3D10_TEXTURE2D_DESC));
|
||||
desc.ArraySize = 1;
|
||||
desc.MipLevels = 1;
|
||||
desc.Width = visibleRect.width;
|
||||
desc.Height = visibleRect.height;
|
||||
desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
device()->CreateTexture2D(&desc, NULL, getter_AddRefs(renderTexture));
|
||||
|
||||
device()->CreateRenderTargetView(renderTexture, NULL, getter_AddRefs(rtView));
|
||||
|
||||
float black[] = { 0, 0, 0, 0};
|
||||
device()->ClearRenderTargetView(rtView, black);
|
||||
|
||||
ID3D10RenderTargetView *rtViewPtr = rtView;
|
||||
device()->OMSetRenderTargets(1, &rtViewPtr, NULL);
|
||||
|
||||
effect()->GetVariableByName("vRenderTargetOffset")->
|
||||
GetRawValue(previousRenderTargetOffset, 0, 8);
|
||||
|
||||
renderTargetOffset[0] = (float)visibleRect.x;
|
||||
renderTargetOffset[1] = (float)visibleRect.y;
|
||||
effect()->GetVariableByName("vRenderTargetOffset")->
|
||||
SetRawValue(renderTargetOffset, 0, 8);
|
||||
|
||||
previousViewportSize = mD3DManager->GetViewport();
|
||||
mD3DManager->SetViewport(nsIntSize(visibleRect.Size()));
|
||||
}
|
||||
|
||||
/*
|
||||
* Render this container's contents.
|
||||
*/
|
||||
LayerD3D10 *layerToRender = GetFirstChildD3D10();
|
||||
while (layerToRender) {
|
||||
const nsIntRect *clipRect = layerToRender->GetLayer()->GetClipRect();
|
||||
|
||||
D3D10_RECT oldScissor;
|
||||
if (clipRect || useIntermediate) {
|
||||
UINT numRects = 1;
|
||||
device()->RSGetScissorRects(&numRects, &oldScissor);
|
||||
|
||||
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 {
|
||||
// useIntermediate == true
|
||||
r.left = 0;
|
||||
r.top = 0;
|
||||
r.right = visibleRect.width;
|
||||
r.bottom = visibleRect.height;
|
||||
}
|
||||
|
||||
D3D10_RECT d3drect;
|
||||
if (!useIntermediate) {
|
||||
// Scissor rect should be an intersection of the old and current scissor.
|
||||
r.left = NS_MAX<PRInt32>(oldScissor.left, r.left);
|
||||
r.right = NS_MIN<PRInt32>(oldScissor.right, r.right);
|
||||
r.top = NS_MAX<PRInt32>(oldScissor.top, r.top);
|
||||
r.bottom = NS_MIN<PRInt32>(oldScissor.bottom, r.bottom);
|
||||
}
|
||||
|
||||
if (r.left >= r.right || r.top >= r.bottom) {
|
||||
// Entire layer's clipped out, don't bother drawing.
|
||||
Layer *nextSibling = layerToRender->GetLayer()->GetNextSibling();
|
||||
layerToRender = nextSibling ? static_cast<LayerD3D10*>(nextSibling->
|
||||
ImplData())
|
||||
: nsnull;
|
||||
continue;
|
||||
}
|
||||
|
||||
d3drect.left = NS_MAX<PRInt32>(r.left, 0);
|
||||
d3drect.top = NS_MAX<PRInt32>(r.top, 0);
|
||||
d3drect.bottom = r.bottom;
|
||||
d3drect.right = r.right;
|
||||
|
||||
device()->RSSetScissorRects(1, &d3drect);
|
||||
}
|
||||
|
||||
// SetScissorRect
|
||||
if (!useIntermediate) {
|
||||
layerToRender->RenderLayer(opacity, transform);
|
||||
} else {
|
||||
layerToRender->RenderLayer(1.0f, gfx3DMatrix());
|
||||
}
|
||||
|
||||
if (clipRect || useIntermediate) {
|
||||
device()->RSSetScissorRects(1, &oldScissor);
|
||||
}
|
||||
|
||||
Layer *nextSibling = layerToRender->GetLayer()->GetNextSibling();
|
||||
layerToRender = nextSibling ? static_cast<LayerD3D10*>(nextSibling->
|
||||
ImplData())
|
||||
: nsnull;
|
||||
}
|
||||
|
||||
if (useIntermediate) {
|
||||
mD3DManager->SetViewport(previousViewportSize);
|
||||
ID3D10RenderTargetView *rtView = previousRTView;
|
||||
device()->OMSetRenderTargets(1, &rtView, NULL);
|
||||
effect()->GetVariableByName("vRenderTargetOffset")->
|
||||
SetRawValue(previousRenderTargetOffset, 0, 8);
|
||||
|
||||
effect()->GetVariableByName("mLayerTransform")->SetRawValue(&transform._11, 0, 64);
|
||||
effect()->GetVariableByName("fLayerOpacity")->AsScalar()->SetFloat(opacity);
|
||||
|
||||
ID3D10EffectTechnique *technique;
|
||||
technique = effect()->GetTechniqueByName("RenderRGBALayerPremul");
|
||||
|
||||
effect()->GetVariableByName("vLayerQuad")->AsVector()->SetFloatVector(
|
||||
ShaderConstantRectD3D10(
|
||||
(float)visibleRect.x,
|
||||
(float)visibleRect.y,
|
||||
(float)visibleRect.width,
|
||||
(float)visibleRect.height)
|
||||
);
|
||||
|
||||
technique->GetPassByIndex(0)->Apply(0);
|
||||
|
||||
ID3D10ShaderResourceView *view;
|
||||
device()->CreateShaderResourceView(renderTexture, NULL, &view);
|
||||
device()->PSSetShaderResources(0, 1, &view);
|
||||
device()->Draw(4, 0);
|
||||
view->Release();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ContainerLayerD3D10::LayerManagerDestroyed()
|
||||
{
|
||||
while (mFirstChild) {
|
||||
GetFirstChildD3D10()->LayerManagerDestroyed();
|
||||
RemoveChild(mFirstChild);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ContainerLayerD3D10::Validate()
|
||||
{
|
||||
Layer *layer = GetFirstChild();
|
||||
while (layer) {
|
||||
static_cast<LayerD3D10*>(layer->ImplData())->Validate();
|
||||
layer = layer->GetNextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ContainerLayerD3D10::ShouldUseIntermediate(float aOpacity,
|
||||
const gfx3DMatrix &aMatrix)
|
||||
{
|
||||
if (aOpacity == 1.0f && aMatrix.IsIdentity()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Layer *firstChild = GetFirstChild();
|
||||
|
||||
if (!firstChild || (!firstChild->GetNextSibling() &&
|
||||
!firstChild->GetClipRect())) {
|
||||
// If we forward our transform to a child without using an intermediate, we
|
||||
// need to be sure that child does not have a clip rect since the clip rect
|
||||
// needs to be applied after its transform.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aMatrix.IsIdentity() && (!firstChild || !firstChild->GetNextSibling())) {
|
||||
// If there's no transforms applied and a single child, opacity can always
|
||||
// be forwarded to our only child.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} /* layers */
|
||||
} /* mozilla */
|
|
@ -0,0 +1,78 @@
|
|||
/* -*- 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_CONTAINERLAYERD3D10_H
|
||||
#define GFX_CONTAINERLAYERD3D10_H
|
||||
|
||||
#include "Layers.h"
|
||||
#include "LayerManagerD3D10.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class ContainerLayerD3D10 : public ContainerLayer,
|
||||
public LayerD3D10
|
||||
{
|
||||
public:
|
||||
ContainerLayerD3D10(LayerManagerD3D10 *aManager);
|
||||
~ContainerLayerD3D10();
|
||||
|
||||
nsIntRect GetVisibleRect() { return mVisibleRegion.GetBounds(); }
|
||||
|
||||
/* ContainerLayer implementation */
|
||||
virtual void InsertAfter(Layer* aChild, Layer* aAfter);
|
||||
|
||||
virtual void RemoveChild(Layer* aChild);
|
||||
|
||||
/* LayerD3D10 implementation */
|
||||
Layer* GetLayer();
|
||||
|
||||
LayerD3D10* GetFirstChildD3D10();
|
||||
|
||||
void RenderLayer(float aOpacity, const gfx3DMatrix &aTransform);
|
||||
void Validate();
|
||||
|
||||
virtual void LayerManagerDestroyed();
|
||||
|
||||
private:
|
||||
bool ShouldUseIntermediate(float aOpacity, const gfx3DMatrix &aTransform);
|
||||
};
|
||||
|
||||
} /* layers */
|
||||
} /* mozilla */
|
||||
|
||||
#endif /* GFX_CONTAINERLAYERD3D10_H */
|
|
@ -0,0 +1,395 @@
|
|||
/* -*- 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) 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 "ImageLayerD3D10.h"
|
||||
#include "gfxImageSurface.h"
|
||||
#include "yuv_convert.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
using mozilla::MutexAutoLock;
|
||||
|
||||
ImageContainerD3D10::ImageContainerD3D10(LayerManagerD3D10 *aManager)
|
||||
: ImageContainer(aManager)
|
||||
, mActiveImageLock("mozilla.layers.ImageContainerD3D10.mActiveImageLock")
|
||||
{
|
||||
}
|
||||
|
||||
already_AddRefed<Image>
|
||||
ImageContainerD3D10::CreateImage(const Image::Format *aFormats,
|
||||
PRUint32 aNumFormats)
|
||||
{
|
||||
if (!aNumFormats) {
|
||||
return nsnull;
|
||||
}
|
||||
nsRefPtr<Image> img;
|
||||
if (aFormats[0] == Image::PLANAR_YCBCR) {
|
||||
img = new PlanarYCbCrImageD3D10(static_cast<LayerManagerD3D10*>(mManager));
|
||||
} else if (aFormats[0] == Image::CAIRO_SURFACE) {
|
||||
img = new CairoImageD3D10(static_cast<LayerManagerD3D10*>(mManager));
|
||||
}
|
||||
return img.forget();
|
||||
}
|
||||
|
||||
void
|
||||
ImageContainerD3D10::SetCurrentImage(Image *aImage)
|
||||
{
|
||||
MutexAutoLock lock(mActiveImageLock);
|
||||
|
||||
mActiveImage = aImage;
|
||||
}
|
||||
|
||||
already_AddRefed<Image>
|
||||
ImageContainerD3D10::GetCurrentImage()
|
||||
{
|
||||
MutexAutoLock lock(mActiveImageLock);
|
||||
|
||||
nsRefPtr<Image> retval = mActiveImage;
|
||||
return retval.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<gfxASurface>
|
||||
ImageContainerD3D10::GetCurrentAsSurface(gfxIntSize *aSize)
|
||||
{
|
||||
MutexAutoLock lock(mActiveImageLock);
|
||||
if (!mActiveImage) {
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if (mActiveImage->GetFormat() == Image::PLANAR_YCBCR) {
|
||||
PlanarYCbCrImageD3D10 *yuvImage =
|
||||
static_cast<PlanarYCbCrImageD3D10*>(mActiveImage.get());
|
||||
if (yuvImage->HasData()) {
|
||||
*aSize = yuvImage->mSize;
|
||||
}
|
||||
} else if (mActiveImage->GetFormat() == Image::CAIRO_SURFACE) {
|
||||
CairoImageD3D10 *cairoImage =
|
||||
static_cast<CairoImageD3D10*>(mActiveImage.get());
|
||||
*aSize = cairoImage->mSize;
|
||||
}
|
||||
|
||||
return static_cast<ImageD3D10*>(mActiveImage->GetImplData())->GetAsSurface();
|
||||
}
|
||||
|
||||
gfxIntSize
|
||||
ImageContainerD3D10::GetCurrentSize()
|
||||
{
|
||||
MutexAutoLock lock(mActiveImageLock);
|
||||
if (!mActiveImage) {
|
||||
return gfxIntSize(0,0);
|
||||
}
|
||||
if (mActiveImage->GetFormat() == Image::PLANAR_YCBCR) {
|
||||
PlanarYCbCrImageD3D10 *yuvImage =
|
||||
static_cast<PlanarYCbCrImageD3D10*>(mActiveImage.get());
|
||||
if (!yuvImage->HasData()) {
|
||||
return gfxIntSize(0,0);
|
||||
}
|
||||
return yuvImage->mSize;
|
||||
|
||||
} else if (mActiveImage->GetFormat() == Image::CAIRO_SURFACE) {
|
||||
CairoImageD3D10 *cairoImage =
|
||||
static_cast<CairoImageD3D10*>(mActiveImage.get());
|
||||
return cairoImage->mSize;
|
||||
}
|
||||
|
||||
return gfxIntSize(0,0);
|
||||
}
|
||||
|
||||
PRBool
|
||||
ImageContainerD3D10::SetLayerManager(LayerManager *aManager)
|
||||
{
|
||||
// we can't do anything here for now
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
Layer*
|
||||
ImageLayerD3D10::GetLayer()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
void
|
||||
ImageLayerD3D10::RenderLayer(float aOpacity, const gfx3DMatrix &aTransform)
|
||||
{
|
||||
if (!GetContainer()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<Image> image = GetContainer()->GetCurrentImage();
|
||||
|
||||
|
||||
gfx3DMatrix transform = mTransform * aTransform;
|
||||
effect()->GetVariableByName("mLayerTransform")->SetRawValue(&transform._11, 0, 64);
|
||||
effect()->GetVariableByName("fLayerOpacity")->AsScalar()->SetFloat(GetOpacity() * aOpacity);
|
||||
|
||||
ID3D10EffectTechnique *technique;
|
||||
|
||||
if (image->GetFormat() == Image::PLANAR_YCBCR) {
|
||||
PlanarYCbCrImageD3D10 *yuvImage =
|
||||
static_cast<PlanarYCbCrImageD3D10*>(image.get());
|
||||
|
||||
if (!yuvImage->HasData()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: At some point we should try to deal with mFilter here, you don't
|
||||
// really want to use point filtering in the case of NEAREST, since that
|
||||
// would also use point filtering for Chroma upsampling. Where most likely
|
||||
// the user would only want point filtering for final RGB image upsampling.
|
||||
|
||||
technique = effect()->GetTechniqueByName("RenderYCbCrLayer");
|
||||
|
||||
effect()->GetVariableByName("tY")->AsShaderResource()->SetResource(yuvImage->mYView);
|
||||
effect()->GetVariableByName("tCb")->AsShaderResource()->SetResource(yuvImage->mCbView);
|
||||
effect()->GetVariableByName("tCr")->AsShaderResource()->SetResource(yuvImage->mCrView);
|
||||
|
||||
effect()->GetVariableByName("vLayerQuad")->AsVector()->SetFloatVector(
|
||||
ShaderConstantRectD3D10(
|
||||
(float)0,
|
||||
(float)0,
|
||||
(float)yuvImage->mSize.width,
|
||||
(float)yuvImage->mSize.height)
|
||||
);
|
||||
} else if (image->GetFormat() == Image::CAIRO_SURFACE) {
|
||||
CairoImageD3D10 *cairoImage =
|
||||
static_cast<CairoImageD3D10*>(image.get());
|
||||
|
||||
if (mFilter == gfxPattern::FILTER_NEAREST) {
|
||||
technique = effect()->GetTechniqueByName("RenderRGBALayerPremulPoint");
|
||||
} else {
|
||||
technique = effect()->GetTechniqueByName("RenderRGBALayerPremul");
|
||||
}
|
||||
|
||||
if (cairoImage->mSRView) {
|
||||
effect()->GetVariableByName("tRGB")->AsShaderResource()->SetResource(cairoImage->mSRView);
|
||||
}
|
||||
|
||||
effect()->GetVariableByName("vLayerQuad")->AsVector()->SetFloatVector(
|
||||
ShaderConstantRectD3D10(
|
||||
(float)0,
|
||||
(float)0,
|
||||
(float)cairoImage->mSize.width,
|
||||
(float)cairoImage->mSize.height)
|
||||
);
|
||||
}
|
||||
|
||||
technique->GetPassByIndex(0)->Apply(0);
|
||||
device()->Draw(4, 0);
|
||||
}
|
||||
|
||||
PlanarYCbCrImageD3D10::PlanarYCbCrImageD3D10(mozilla::layers::LayerManagerD3D10* aManager)
|
||||
: PlanarYCbCrImage(static_cast<ImageD3D10*>(this))
|
||||
, mManager(aManager)
|
||||
, mHasData(PR_FALSE)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
PlanarYCbCrImageD3D10::SetData(const PlanarYCbCrImage::Data &aData)
|
||||
{
|
||||
// XXX - For D3D10Ex we really should just copy to systemmem surfaces here.
|
||||
// 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;
|
||||
mType = gfx::YV24;
|
||||
} else if (aData.mYSize.width / 2 == aData.mCbCrSize.width &&
|
||||
aData.mYSize.height == aData.mCbCrSize.height) {
|
||||
// YV16 format
|
||||
width_shift = 1;
|
||||
height_shift = 0;
|
||||
mType = gfx::YV16;
|
||||
} else if (aData.mYSize.width / 2 == aData.mCbCrSize.width &&
|
||||
aData.mYSize.height / 2 == aData.mCbCrSize.height ) {
|
||||
// YV12 format
|
||||
width_shift = 1;
|
||||
height_shift = 1;
|
||||
mType = gfx::YV12;
|
||||
} else {
|
||||
NS_ERROR("YCbCr format not supported");
|
||||
}
|
||||
|
||||
mData = aData;
|
||||
mData.mCbCrStride = mData.mCbCrSize.width = aData.mPicSize.width >> width_shift;
|
||||
// Round up the values for width and height to make sure we sample enough data
|
||||
// for the last pixel - See bug 590735
|
||||
if (width_shift && (aData.mPicSize.width & 1)) {
|
||||
mData.mCbCrStride++;
|
||||
mData.mCbCrSize.width++;
|
||||
}
|
||||
mData.mCbCrSize.height = aData.mPicSize.height >> height_shift;
|
||||
if (height_shift && (aData.mPicSize.height & 1)) {
|
||||
mData.mCbCrSize.height++;
|
||||
}
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
AllocateTextures();
|
||||
|
||||
mHasData = PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
PlanarYCbCrImageD3D10::AllocateTextures()
|
||||
{
|
||||
D3D10_SUBRESOURCE_DATA dataY;
|
||||
D3D10_SUBRESOURCE_DATA dataCb;
|
||||
D3D10_SUBRESOURCE_DATA dataCr;
|
||||
CD3D10_TEXTURE2D_DESC descY(DXGI_FORMAT_R8_UNORM,
|
||||
mData.mYSize.width,
|
||||
mData.mYSize.height, 1, 1);
|
||||
CD3D10_TEXTURE2D_DESC descCbCr(DXGI_FORMAT_R8_UNORM,
|
||||
mData.mCbCrSize.width,
|
||||
mData.mCbCrSize.height, 1, 1);
|
||||
|
||||
descY.Usage = descCbCr.Usage = D3D10_USAGE_IMMUTABLE;
|
||||
|
||||
dataY.pSysMem = mData.mYChannel;
|
||||
dataY.SysMemPitch = mData.mYStride;
|
||||
dataCb.pSysMem = mData.mCbChannel;
|
||||
dataCb.SysMemPitch = mData.mCbCrStride;
|
||||
dataCr.pSysMem = mData.mCrChannel;
|
||||
dataCr.SysMemPitch = mData.mCbCrStride;
|
||||
|
||||
mManager->device()->CreateTexture2D(&descY, &dataY, getter_AddRefs(mYTexture));
|
||||
mManager->device()->CreateTexture2D(&descCbCr, &dataCb, getter_AddRefs(mCbTexture));
|
||||
mManager->device()->CreateTexture2D(&descCbCr, &dataCr, getter_AddRefs(mCrTexture));
|
||||
mManager->device()->CreateShaderResourceView(mYTexture, NULL, getter_AddRefs(mYView));
|
||||
mManager->device()->CreateShaderResourceView(mCbTexture, NULL, getter_AddRefs(mCbView));
|
||||
mManager->device()->CreateShaderResourceView(mCrTexture, NULL, getter_AddRefs(mCrView));
|
||||
}
|
||||
|
||||
already_AddRefed<gfxASurface>
|
||||
PlanarYCbCrImageD3D10::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(),
|
||||
mType);
|
||||
|
||||
return imageSurface.forget().get();
|
||||
}
|
||||
|
||||
CairoImageD3D10::~CairoImageD3D10()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
CairoImageD3D10::SetData(const CairoImage::Data &aData)
|
||||
{
|
||||
mSize = aData.mSize;
|
||||
|
||||
nsRefPtr<gfxImageSurface> imageSurface;
|
||||
|
||||
if (aData.mSurface->GetType() == gfxASurface::SurfaceTypeImage) {
|
||||
imageSurface = static_cast<gfxImageSurface*>(aData.mSurface);
|
||||
} else {
|
||||
imageSurface = new gfxImageSurface(aData.mSize,
|
||||
gfxASurface::ImageFormatARGB32);
|
||||
|
||||
nsRefPtr<gfxContext> context = new gfxContext(imageSurface);
|
||||
context->SetSource(aData.mSurface);
|
||||
context->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
context->Paint();
|
||||
}
|
||||
|
||||
D3D10_SUBRESOURCE_DATA data;
|
||||
|
||||
CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, mSize.width, mSize.height, 1, 1);
|
||||
desc.Usage = D3D10_USAGE_IMMUTABLE;
|
||||
|
||||
data.pSysMem = imageSurface->Data();
|
||||
data.SysMemPitch = imageSurface->Stride();
|
||||
|
||||
mManager->device()->CreateTexture2D(&desc, &data, getter_AddRefs(mTexture));
|
||||
mManager->device()->CreateShaderResourceView(mTexture, NULL, getter_AddRefs(mSRView));
|
||||
}
|
||||
|
||||
already_AddRefed<gfxASurface>
|
||||
CairoImageD3D10::GetAsSurface()
|
||||
{
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
} /* layers */
|
||||
} /* mozilla */
|
|
@ -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_IMAGELAYERD3D10_H
|
||||
#define GFX_IMAGELAYERD3D10_H
|
||||
|
||||
#include "LayerManagerD3D10.h"
|
||||
#include "ImageLayers.h"
|
||||
#include "yuv_convert.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class THEBES_API ImageContainerD3D10 : public ImageContainer
|
||||
{
|
||||
public:
|
||||
ImageContainerD3D10(LayerManagerD3D10 *aManager);
|
||||
virtual ~ImageContainerD3D10() {}
|
||||
|
||||
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();
|
||||
|
||||
virtual PRBool SetLayerManager(LayerManager *aManager);
|
||||
|
||||
private:
|
||||
typedef mozilla::Mutex Mutex;
|
||||
|
||||
nsRefPtr<Image> mActiveImage;
|
||||
|
||||
Mutex mActiveImageLock;
|
||||
};
|
||||
|
||||
class THEBES_API ImageLayerD3D10 : public ImageLayer,
|
||||
public LayerD3D10
|
||||
{
|
||||
public:
|
||||
ImageLayerD3D10(LayerManagerD3D10 *aManager)
|
||||
: ImageLayer(aManager, NULL)
|
||||
, LayerD3D10(aManager)
|
||||
{
|
||||
mImplData = static_cast<LayerD3D10*>(this);
|
||||
}
|
||||
|
||||
// LayerD3D10 Implementation
|
||||
virtual Layer* GetLayer();
|
||||
|
||||
virtual void RenderLayer(float aOpacity, const gfx3DMatrix &aTransform);
|
||||
};
|
||||
|
||||
class THEBES_API ImageD3D10
|
||||
{
|
||||
public:
|
||||
virtual already_AddRefed<gfxASurface> GetAsSurface() = 0;
|
||||
};
|
||||
|
||||
class THEBES_API PlanarYCbCrImageD3D10 : public PlanarYCbCrImage,
|
||||
public ImageD3D10
|
||||
{
|
||||
public:
|
||||
PlanarYCbCrImageD3D10(LayerManagerD3D10 *aManager);
|
||||
~PlanarYCbCrImageD3D10() {}
|
||||
|
||||
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();
|
||||
|
||||
PRBool HasData() { return mHasData; }
|
||||
|
||||
virtual already_AddRefed<gfxASurface> GetAsSurface();
|
||||
|
||||
nsAutoArrayPtr<PRUint8> mBuffer;
|
||||
LayerManagerD3D10 *mManager;
|
||||
Data mData;
|
||||
gfxIntSize mSize;
|
||||
nsRefPtr<ID3D10Texture2D> mYTexture;
|
||||
nsRefPtr<ID3D10Texture2D> mCrTexture;
|
||||
nsRefPtr<ID3D10Texture2D> mCbTexture;
|
||||
nsRefPtr<ID3D10ShaderResourceView> mYView;
|
||||
nsRefPtr<ID3D10ShaderResourceView> mCbView;
|
||||
nsRefPtr<ID3D10ShaderResourceView> mCrView;
|
||||
PRPackedBool mHasData;
|
||||
gfx::YUVType mType;
|
||||
};
|
||||
|
||||
|
||||
class THEBES_API CairoImageD3D10 : public CairoImage,
|
||||
public ImageD3D10
|
||||
{
|
||||
public:
|
||||
CairoImageD3D10(LayerManagerD3D10 *aManager)
|
||||
: CairoImage(static_cast<ImageD3D10*>(this))
|
||||
, mManager(aManager)
|
||||
{ }
|
||||
~CairoImageD3D10();
|
||||
|
||||
virtual void SetData(const Data &aData);
|
||||
|
||||
virtual already_AddRefed<gfxASurface> GetAsSurface();
|
||||
|
||||
nsRefPtr<ID3D10Texture2D> mTexture;
|
||||
nsRefPtr<ID3D10ShaderResourceView> mSRView;
|
||||
gfxIntSize mSize;
|
||||
LayerManagerD3D10 *mManager;
|
||||
};
|
||||
|
||||
} /* layers */
|
||||
} /* mozilla */
|
||||
#endif /* GFX_IMAGELAYERD3D10_H */
|
|
@ -0,0 +1,502 @@
|
|||
/* -*- 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 "LayerManagerD3D10.h"
|
||||
#include "LayerManagerD3D10Effect.h"
|
||||
#include "gfxWindowsPlatform.h"
|
||||
#include "gfxD2DSurface.h"
|
||||
#include "cairo-win32.h"
|
||||
#include "dxgi.h"
|
||||
|
||||
#include "ContainerLayerD3D10.h"
|
||||
#include "ThebesLayerD3D10.h"
|
||||
#include "ColorLayerD3D10.h"
|
||||
#include "CanvasLayerD3D10.h"
|
||||
#include "ImageLayerD3D10.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
typedef HRESULT (WINAPI*D3D10CreateEffectFromMemoryFunc)(
|
||||
void *pData,
|
||||
SIZE_T DataLength,
|
||||
UINT FXFlags,
|
||||
ID3D10Device *pDevice,
|
||||
ID3D10EffectPool *pEffectPool,
|
||||
ID3D10Effect **ppEffect
|
||||
);
|
||||
|
||||
struct Vertex
|
||||
{
|
||||
float position[2];
|
||||
};
|
||||
|
||||
// {17F88CCB-1F49-4c08-8002-ADA7BD44856D}
|
||||
static const GUID sEffect =
|
||||
{ 0x17f88ccb, 0x1f49, 0x4c08, { 0x80, 0x2, 0xad, 0xa7, 0xbd, 0x44, 0x85, 0x6d } };
|
||||
// {19599D91-912C-4C2F-A8C5-299DE85FBD34}
|
||||
static const GUID sInputLayout =
|
||||
{ 0x19599d91, 0x912c, 0x4c2f, { 0xa8, 0xc5, 0x29, 0x9d, 0xe8, 0x5f, 0xbd, 0x34 } };
|
||||
// {293157D2-09C7-4680-AE27-C28E370E418B}
|
||||
static const GUID sVertexBuffer =
|
||||
{ 0x293157d2, 0x9c7, 0x4680, { 0xae, 0x27, 0xc2, 0x8e, 0x37, 0xe, 0x41, 0x8b } };
|
||||
|
||||
cairo_user_data_key_t gKeyD3D10Texture;
|
||||
|
||||
LayerManagerD3D10::LayerManagerD3D10(nsIWidget *aWidget)
|
||||
: mWidget(aWidget)
|
||||
{
|
||||
}
|
||||
|
||||
LayerManagerD3D10::~LayerManagerD3D10()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
LayerManagerD3D10::Initialize()
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
cairo_device_t *device = gfxWindowsPlatform::GetPlatform()->GetD2DDevice();
|
||||
if (!device) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mDevice = cairo_d2d_device_get_device(device);
|
||||
|
||||
UINT size = 4;
|
||||
if (FAILED(mDevice->GetPrivateData(sEffect, &size, mEffect.StartAssignment()))) {
|
||||
D3D10CreateEffectFromMemoryFunc createEffect = (D3D10CreateEffectFromMemoryFunc)
|
||||
GetProcAddress(LoadLibraryA("d3d10_1.dll"), "D3D10CreateEffectFromMemory");
|
||||
|
||||
if (!createEffect) {
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = createEffect((void*)g_main,
|
||||
sizeof(g_main),
|
||||
D3D10_EFFECT_SINGLE_THREADED,
|
||||
mDevice,
|
||||
NULL,
|
||||
getter_AddRefs(mEffect));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mDevice->SetPrivateDataInterface(sEffect, mEffect);
|
||||
}
|
||||
|
||||
size = 4;
|
||||
if (FAILED(mDevice->GetPrivateData(sInputLayout, &size, mInputLayout.StartAssignment()))) {
|
||||
D3D10_INPUT_ELEMENT_DESC layout[] =
|
||||
{
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
|
||||
};
|
||||
D3D10_PASS_DESC passDesc;
|
||||
mEffect->GetTechniqueByName("RenderRGBLayerPremul")->GetPassByIndex(0)->
|
||||
GetDesc(&passDesc);
|
||||
|
||||
hr = mDevice->CreateInputLayout(layout,
|
||||
sizeof(layout) / sizeof(D3D10_INPUT_ELEMENT_DESC),
|
||||
passDesc.pIAInputSignature,
|
||||
passDesc.IAInputSignatureSize,
|
||||
getter_AddRefs(mInputLayout));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mDevice->SetPrivateDataInterface(sInputLayout, mInputLayout);
|
||||
}
|
||||
|
||||
size = 4;
|
||||
if (FAILED(mDevice->GetPrivateData(sVertexBuffer, &size, mVertexBuffer.StartAssignment()))) {
|
||||
Vertex vertices[] = { {0.0, 0.0}, {1.0, 0.0}, {0.0, 1.0}, {1.0, 1.0} };
|
||||
CD3D10_BUFFER_DESC bufferDesc(sizeof(vertices), D3D10_BIND_VERTEX_BUFFER);
|
||||
D3D10_SUBRESOURCE_DATA data;
|
||||
data.pSysMem = (void*)vertices;
|
||||
|
||||
hr = mDevice->CreateBuffer(&bufferDesc, &data, getter_AddRefs(mVertexBuffer));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mDevice->SetPrivateDataInterface(sVertexBuffer, mVertexBuffer);
|
||||
}
|
||||
|
||||
nsRefPtr<IDXGIDevice> dxgiDevice;
|
||||
nsRefPtr<IDXGIAdapter> dxgiAdapter;
|
||||
nsRefPtr<IDXGIFactory> dxgiFactory;
|
||||
|
||||
mDevice->QueryInterface(dxgiDevice.StartAssignment());
|
||||
dxgiDevice->GetAdapter(getter_AddRefs(dxgiAdapter));
|
||||
|
||||
dxgiAdapter->GetParent(IID_PPV_ARGS(dxgiFactory.StartAssignment()));
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC swapDesc;
|
||||
::ZeroMemory(&swapDesc, sizeof(swapDesc));
|
||||
|
||||
swapDesc.BufferDesc.Width = 0;
|
||||
swapDesc.BufferDesc.Height = 0;
|
||||
swapDesc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
swapDesc.BufferDesc.RefreshRate.Numerator = 60;
|
||||
swapDesc.BufferDesc.RefreshRate.Denominator = 1;
|
||||
swapDesc.SampleDesc.Count = 1;
|
||||
swapDesc.SampleDesc.Quality = 0;
|
||||
swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
swapDesc.BufferCount = 1;
|
||||
swapDesc.OutputWindow = (HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW);
|
||||
swapDesc.Windowed = TRUE;
|
||||
|
||||
/**
|
||||
* Create a swap chain, this swap chain will contain the backbuffer for
|
||||
* the window we draw to. The front buffer is the full screen front
|
||||
* buffer.
|
||||
*/
|
||||
hr = dxgiFactory->CreateSwapChain(dxgiDevice, &swapDesc, getter_AddRefs(mSwapChain));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D10::SetRoot(Layer *aRoot)
|
||||
{
|
||||
mRoot = aRoot;
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D10::BeginTransaction()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D10::BeginTransactionWithTarget(gfxContext* aTarget)
|
||||
{
|
||||
mTarget = aTarget;
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D10::EndTransaction(DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData)
|
||||
{
|
||||
mCurrentCallbackInfo.Callback = aCallback;
|
||||
mCurrentCallbackInfo.CallbackData = aCallbackData;
|
||||
Render();
|
||||
mCurrentCallbackInfo.Callback = nsnull;
|
||||
mCurrentCallbackInfo.CallbackData = nsnull;
|
||||
mTarget = nsnull;
|
||||
}
|
||||
|
||||
already_AddRefed<ThebesLayer>
|
||||
LayerManagerD3D10::CreateThebesLayer()
|
||||
{
|
||||
nsRefPtr<ThebesLayer> layer = new ThebesLayerD3D10(this);
|
||||
return layer.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<ContainerLayer>
|
||||
LayerManagerD3D10::CreateContainerLayer()
|
||||
{
|
||||
nsRefPtr<ContainerLayer> layer = new ContainerLayerD3D10(this);
|
||||
return layer.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<ImageLayer>
|
||||
LayerManagerD3D10::CreateImageLayer()
|
||||
{
|
||||
nsRefPtr<ImageLayer> layer = new ImageLayerD3D10(this);
|
||||
return layer.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<ColorLayer>
|
||||
LayerManagerD3D10::CreateColorLayer()
|
||||
{
|
||||
nsRefPtr<ColorLayer> layer = new ColorLayerD3D10(this);
|
||||
return layer.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<CanvasLayer>
|
||||
LayerManagerD3D10::CreateCanvasLayer()
|
||||
{
|
||||
nsRefPtr<CanvasLayer> layer = new CanvasLayerD3D10(this);
|
||||
return layer.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<ImageContainer>
|
||||
LayerManagerD3D10::CreateImageContainer()
|
||||
{
|
||||
nsRefPtr<ImageContainer> layer = new ImageContainerD3D10(this);
|
||||
return layer.forget();
|
||||
}
|
||||
|
||||
static void ReleaseTexture(void *texture)
|
||||
{
|
||||
static_cast<ID3D10Texture2D*>(texture)->Release();
|
||||
}
|
||||
|
||||
already_AddRefed<gfxASurface>
|
||||
LayerManagerD3D10::CreateOptimalSurface(const gfxIntSize &aSize,
|
||||
gfxASurface::gfxImageFormat aFormat)
|
||||
{
|
||||
if ((aFormat != gfxASurface::ImageFormatRGB24 &&
|
||||
aFormat != gfxASurface::ImageFormatARGB32)) {
|
||||
return LayerManager::CreateOptimalSurface(aSize, aFormat);
|
||||
}
|
||||
|
||||
nsRefPtr<ID3D10Texture2D> texture;
|
||||
|
||||
CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, aSize.width, aSize.height, 1, 1);
|
||||
desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
|
||||
desc.MiscFlags = D3D10_RESOURCE_MISC_GDI_COMPATIBLE;
|
||||
|
||||
HRESULT hr = device()->CreateTexture2D(&desc, NULL, getter_AddRefs(texture));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to create new texture for CreateOptimalSurface!");
|
||||
return LayerManager::CreateOptimalSurface(aSize, aFormat);
|
||||
}
|
||||
|
||||
nsRefPtr<gfxD2DSurface> surface =
|
||||
new gfxD2DSurface(texture, aFormat == gfxASurface::ImageFormatRGB24 ?
|
||||
gfxASurface::CONTENT_COLOR : gfxASurface::CONTENT_COLOR_ALPHA);
|
||||
|
||||
if (!surface || surface->CairoStatus()) {
|
||||
return LayerManager::CreateOptimalSurface(aSize, aFormat);
|
||||
}
|
||||
|
||||
surface->SetData(&gKeyD3D10Texture,
|
||||
texture.forget().get(),
|
||||
ReleaseTexture);
|
||||
|
||||
return surface.forget();
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D10::SetViewport(const nsIntSize &aViewport)
|
||||
{
|
||||
mViewport = aViewport;
|
||||
|
||||
D3D10_VIEWPORT viewport;
|
||||
viewport.MaxDepth = 1.0f;
|
||||
viewport.MinDepth = 0;
|
||||
viewport.Width = aViewport.width;
|
||||
viewport.Height = aViewport.height;
|
||||
viewport.TopLeftX = 0;
|
||||
viewport.TopLeftY = 0;
|
||||
|
||||
mDevice->RSSetViewports(1, &viewport);
|
||||
|
||||
gfx3DMatrix projection;
|
||||
/*
|
||||
* Matrix to transform to viewport space ( <-1.0, 1.0> topleft,
|
||||
* <1.0, -1.0> bottomright)
|
||||
*/
|
||||
projection._11 = 2.0f / aViewport.width;
|
||||
projection._22 = -2.0f / aViewport.height;
|
||||
projection._33 = 1.0f;
|
||||
projection._41 = -1.0f;
|
||||
projection._42 = 1.0f;
|
||||
projection._44 = 1.0f;
|
||||
|
||||
HRESULT hr = mEffect->GetVariableByName("mProjection")->
|
||||
SetRawValue(&projection._11, 0, 64);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to set projection matrix.");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D10::SetupPipeline()
|
||||
{
|
||||
VerifyBufferSize();
|
||||
UpdateRenderTarget();
|
||||
|
||||
nsIntRect rect;
|
||||
mWidget->GetClientBounds(rect);
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
hr = mEffect->GetVariableByName("vTextureCoords")->AsVector()->
|
||||
SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to set Texture Coordinates.");
|
||||
return;
|
||||
}
|
||||
|
||||
ID3D10RenderTargetView *view = mRTView;
|
||||
mDevice->OMSetRenderTargets(1, &view, NULL);
|
||||
mDevice->IASetInputLayout(mInputLayout);
|
||||
|
||||
UINT stride = sizeof(Vertex);
|
||||
UINT offset = 0;
|
||||
ID3D10Buffer *buffer = mVertexBuffer;
|
||||
mDevice->IASetVertexBuffers(0, 1, &buffer, &stride, &offset);
|
||||
mDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
||||
|
||||
SetViewport(nsIntSize(rect.width, rect.height));
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D10::UpdateRenderTarget()
|
||||
{
|
||||
if (mRTView) {
|
||||
return;
|
||||
}
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
nsRefPtr<ID3D10Texture2D> backBuf;
|
||||
|
||||
hr = mSwapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), (void**)backBuf.StartAssignment());
|
||||
if (FAILED(hr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mDevice->CreateRenderTargetView(backBuf, NULL, getter_AddRefs(mRTView));
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D10::VerifyBufferSize()
|
||||
{
|
||||
DXGI_SWAP_CHAIN_DESC swapDesc;
|
||||
mSwapChain->GetDesc(&swapDesc);
|
||||
|
||||
nsIntRect rect;
|
||||
mWidget->GetClientBounds(rect);
|
||||
|
||||
if (swapDesc.BufferDesc.Width == rect.width &&
|
||||
swapDesc.BufferDesc.Height == rect.height) {
|
||||
return;
|
||||
}
|
||||
|
||||
mRTView = nsnull;
|
||||
mSwapChain->ResizeBuffers(1, rect.width, rect.height,
|
||||
DXGI_FORMAT_B8G8R8A8_UNORM, 0);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D10::Render()
|
||||
{
|
||||
if (mRoot) {
|
||||
static_cast<LayerD3D10*>(mRoot->ImplData())->Validate();
|
||||
}
|
||||
|
||||
SetupPipeline();
|
||||
|
||||
float black[] = { 0, 0, 0, 0 };
|
||||
device()->ClearRenderTargetView(mRTView, black);
|
||||
|
||||
nsIntRect rect;
|
||||
mWidget->GetClientBounds(rect);
|
||||
|
||||
if (mRoot) {
|
||||
const nsIntRect *clipRect = mRoot->GetClipRect();
|
||||
D3D10_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;
|
||||
}
|
||||
device()->RSSetScissorRects(1, &r);
|
||||
|
||||
static_cast<LayerD3D10*>(mRoot->ImplData())->RenderLayer(1, gfx3DMatrix());
|
||||
}
|
||||
|
||||
if (mTarget) {
|
||||
PaintToTarget();
|
||||
} else {
|
||||
mSwapChain->Present(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LayerManagerD3D10::PaintToTarget()
|
||||
{
|
||||
nsRefPtr<ID3D10Texture2D> backBuf;
|
||||
|
||||
mSwapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), (void**)backBuf.StartAssignment());
|
||||
|
||||
D3D10_TEXTURE2D_DESC bbDesc;
|
||||
backBuf->GetDesc(&bbDesc);
|
||||
|
||||
CD3D10_TEXTURE2D_DESC softDesc(bbDesc.Format, bbDesc.Width, bbDesc.Height);
|
||||
softDesc.MipLevels = 1;
|
||||
softDesc.CPUAccessFlags = D3D10_CPU_ACCESS_READ;
|
||||
softDesc.Usage = D3D10_USAGE_STAGING;
|
||||
softDesc.BindFlags = 0;
|
||||
|
||||
nsRefPtr<ID3D10Texture2D> readTexture;
|
||||
|
||||
device()->CreateTexture2D(&softDesc, NULL, getter_AddRefs(readTexture));
|
||||
|
||||
device()->CopyResource(readTexture, backBuf);
|
||||
|
||||
D3D10_MAPPED_TEXTURE2D map;
|
||||
readTexture->Map(0, D3D10_MAP_READ, 0, &map);
|
||||
|
||||
nsRefPtr<gfxImageSurface> tmpSurface =
|
||||
new gfxImageSurface((unsigned char*)map.pData,
|
||||
gfxIntSize(bbDesc.Width, bbDesc.Height),
|
||||
map.RowPitch,
|
||||
gfxASurface::ImageFormatARGB32);
|
||||
|
||||
mTarget->SetSource(tmpSurface);
|
||||
mTarget->SetOperator(gfxContext::OPERATOR_SOURCE);
|
||||
mTarget->Paint();
|
||||
}
|
||||
|
||||
LayerD3D10::LayerD3D10(LayerManagerD3D10 *aManager)
|
||||
: mD3DManager(aManager)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,248 @@
|
|||
typedef float4 rect;
|
||||
cbuffer PerLayer {
|
||||
rect vTextureCoords;
|
||||
rect vLayerQuad;
|
||||
float fLayerOpacity;
|
||||
float4x4 mLayerTransform;
|
||||
}
|
||||
|
||||
cbuffer PerOccasionalLayer {
|
||||
float4 vRenderTargetOffset;
|
||||
float4 fLayerColor;
|
||||
}
|
||||
|
||||
cbuffer PerLayerManager {
|
||||
float4x4 mProjection;
|
||||
}
|
||||
|
||||
BlendState Premul
|
||||
{
|
||||
AlphaToCoverageEnable = FALSE;
|
||||
BlendEnable[0] = TRUE;
|
||||
SrcBlend = One;
|
||||
DestBlend = Inv_Src_Alpha;
|
||||
BlendOp = Add;
|
||||
SrcBlendAlpha = One;
|
||||
DestBlendAlpha = Inv_Src_Alpha;
|
||||
BlendOpAlpha = Add;
|
||||
RenderTargetWriteMask[0] = 0x0F; // All
|
||||
};
|
||||
|
||||
BlendState NonPremul
|
||||
{
|
||||
AlphaToCoverageEnable = FALSE;
|
||||
BlendEnable[0] = TRUE;
|
||||
SrcBlend = Src_Alpha;
|
||||
DestBlend = Inv_Src_Alpha;
|
||||
BlendOp = Add;
|
||||
SrcBlendAlpha = One;
|
||||
DestBlendAlpha = Inv_Src_Alpha;
|
||||
BlendOpAlpha = Add;
|
||||
RenderTargetWriteMask[0] = 0x0F; // All
|
||||
};
|
||||
|
||||
RasterizerState LayerRast
|
||||
{
|
||||
ScissorEnable = True;
|
||||
};
|
||||
|
||||
Texture2D tRGB;
|
||||
Texture2D tY;
|
||||
Texture2D tCb;
|
||||
Texture2D tCr;
|
||||
|
||||
SamplerState LayerTextureSamplerLinear
|
||||
{
|
||||
Filter = MIN_MAG_MIP_LINEAR;
|
||||
AddressU = Wrap;
|
||||
AddressV = Wrap;
|
||||
};
|
||||
|
||||
SamplerState LayerTextureSamplerPoint
|
||||
{
|
||||
Filter = MIN_MAG_MIP_POINT;
|
||||
AddressU = Wrap;
|
||||
AddressV = Wrap;
|
||||
};
|
||||
|
||||
struct VS_INPUT {
|
||||
float2 vPosition : POSITION;
|
||||
};
|
||||
|
||||
struct VS_OUTPUT {
|
||||
float4 vPosition : SV_Position;
|
||||
float2 vTexCoords : TEXCOORD0;
|
||||
};
|
||||
|
||||
VS_OUTPUT LayerQuadVS(const VS_INPUT aVertex)
|
||||
{
|
||||
VS_OUTPUT outp;
|
||||
outp.vPosition.z = 0;
|
||||
outp.vPosition.w = 1;
|
||||
|
||||
// We use 4 component floats to uniquely describe a rectangle, by the structure
|
||||
// of x, y, width, height. This allows us to easily generate the 4 corners
|
||||
// of any rectangle from the 4 corners of the 0,0-1,1 quad that we use as the
|
||||
// stream source for our LayerQuad vertex shader. We do this by doing:
|
||||
// Xout = x + Xin * width
|
||||
// Yout = y + Yin * height
|
||||
float2 position = vLayerQuad.xy;
|
||||
float2 size = vLayerQuad.zw;
|
||||
outp.vPosition.x = position.x + aVertex.vPosition.x * size.x;
|
||||
outp.vPosition.y = position.y + aVertex.vPosition.y * size.y;
|
||||
|
||||
outp.vPosition = mul(mLayerTransform, outp.vPosition);
|
||||
outp.vPosition = outp.vPosition - vRenderTargetOffset;
|
||||
|
||||
outp.vPosition = mul(mProjection, outp.vPosition);
|
||||
|
||||
position = vTextureCoords.xy;
|
||||
size = vTextureCoords.zw;
|
||||
outp.vTexCoords.x = position.x + aVertex.vPosition.x * size.x;
|
||||
outp.vTexCoords.y = position.y + aVertex.vPosition.y * size.y;
|
||||
return outp;
|
||||
}
|
||||
|
||||
float4 RGBAShaderLinear(const VS_OUTPUT aVertex) : SV_Target
|
||||
{
|
||||
return tRGB.Sample(LayerTextureSamplerLinear, aVertex.vTexCoords) * fLayerOpacity;
|
||||
}
|
||||
|
||||
float4 RGBAShaderPoint(const VS_OUTPUT aVertex) : SV_Target
|
||||
{
|
||||
return tRGB.Sample(LayerTextureSamplerPoint, aVertex.vTexCoords) * fLayerOpacity;
|
||||
}
|
||||
|
||||
float4 RGBShaderLinear(const VS_OUTPUT aVertex) : SV_Target
|
||||
{
|
||||
float4 result;
|
||||
result = tRGB.Sample(LayerTextureSamplerLinear, aVertex.vTexCoords) * fLayerOpacity;
|
||||
result.a = fLayerOpacity;
|
||||
return result;
|
||||
}
|
||||
|
||||
float4 RGBShaderPoint(const VS_OUTPUT aVertex) : SV_Target
|
||||
{
|
||||
float4 result;
|
||||
result = tRGB.Sample(LayerTextureSamplerPoint, aVertex.vTexCoords) * fLayerOpacity;
|
||||
result.a = fLayerOpacity;
|
||||
return result;
|
||||
}
|
||||
|
||||
float4 YCbCrShader(const VS_OUTPUT aVertex) : SV_Target
|
||||
{
|
||||
float4 yuv;
|
||||
float4 color;
|
||||
|
||||
yuv.r = tCr.Sample(LayerTextureSamplerLinear, aVertex.vTexCoords).r - 0.5;
|
||||
yuv.g = tY.Sample(LayerTextureSamplerLinear, aVertex.vTexCoords).r - 0.0625;
|
||||
yuv.b = tCb.Sample(LayerTextureSamplerLinear, 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) : SV_Target
|
||||
{
|
||||
return fLayerColor;
|
||||
}
|
||||
|
||||
technique10 RenderRGBLayerPremul
|
||||
{
|
||||
pass P0
|
||||
{
|
||||
SetRasterizerState( LayerRast );
|
||||
SetBlendState( Premul, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
|
||||
SetVertexShader( CompileShader( vs_4_0_level_9_3, LayerQuadVS() ) );
|
||||
SetGeometryShader( NULL );
|
||||
SetPixelShader( CompileShader( ps_4_0_level_9_3, RGBShaderLinear() ) );
|
||||
}
|
||||
}
|
||||
|
||||
technique10 RenderRGBLayerPremulPoint
|
||||
{
|
||||
pass P0
|
||||
{
|
||||
SetRasterizerState( LayerRast );
|
||||
SetBlendState( Premul, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
|
||||
SetVertexShader( CompileShader( vs_4_0_level_9_3, LayerQuadVS() ) );
|
||||
SetGeometryShader( NULL );
|
||||
SetPixelShader( CompileShader( ps_4_0_level_9_3, RGBShaderPoint() ) );
|
||||
}
|
||||
}
|
||||
|
||||
technique10 RenderRGBALayerPremul
|
||||
{
|
||||
pass P0
|
||||
{
|
||||
SetRasterizerState( LayerRast );
|
||||
SetBlendState( Premul, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
|
||||
SetVertexShader( CompileShader( vs_4_0_level_9_3, LayerQuadVS() ) );
|
||||
SetGeometryShader( NULL );
|
||||
SetPixelShader( CompileShader( ps_4_0_level_9_3, RGBAShaderLinear() ) );
|
||||
}
|
||||
}
|
||||
|
||||
technique10 RenderRGBALayerNonPremul
|
||||
{
|
||||
pass P0
|
||||
{
|
||||
SetRasterizerState( LayerRast );
|
||||
SetBlendState( NonPremul, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
|
||||
SetVertexShader( CompileShader( vs_4_0_level_9_3, LayerQuadVS() ) );
|
||||
SetGeometryShader( NULL );
|
||||
SetPixelShader( CompileShader( ps_4_0_level_9_3, RGBAShaderLinear() ) );
|
||||
}
|
||||
}
|
||||
|
||||
technique10 RenderRGBALayerPremulPoint
|
||||
{
|
||||
pass P0
|
||||
{
|
||||
SetRasterizerState( LayerRast );
|
||||
SetBlendState( Premul, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
|
||||
SetVertexShader( CompileShader( vs_4_0_level_9_3, LayerQuadVS() ) );
|
||||
SetGeometryShader( NULL );
|
||||
SetPixelShader( CompileShader( ps_4_0_level_9_3, RGBAShaderPoint() ) );
|
||||
}
|
||||
}
|
||||
|
||||
technique10 RenderRGBALayerNonPremulPoint
|
||||
{
|
||||
pass P0
|
||||
{
|
||||
SetRasterizerState( LayerRast );
|
||||
SetBlendState( NonPremul, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
|
||||
SetVertexShader( CompileShader( vs_4_0_level_9_3, LayerQuadVS() ) );
|
||||
SetGeometryShader( NULL );
|
||||
SetPixelShader( CompileShader( ps_4_0_level_9_3, RGBAShaderPoint() ) );
|
||||
}
|
||||
}
|
||||
|
||||
technique10 RenderYCbCrLayer
|
||||
{
|
||||
pass P0
|
||||
{
|
||||
SetRasterizerState( LayerRast );
|
||||
SetBlendState( Premul, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
|
||||
SetVertexShader( CompileShader( vs_4_0_level_9_3, LayerQuadVS() ) );
|
||||
SetGeometryShader( NULL );
|
||||
SetPixelShader( CompileShader( ps_4_0_level_9_3, YCbCrShader() ) );
|
||||
}
|
||||
}
|
||||
|
||||
technique10 RenderSolidColorLayer
|
||||
{
|
||||
pass P0
|
||||
{
|
||||
SetRasterizerState( LayerRast );
|
||||
SetBlendState( Premul, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
|
||||
SetVertexShader( CompileShader( vs_4_0_level_9_3, LayerQuadVS() ) );
|
||||
SetGeometryShader( NULL );
|
||||
SetPixelShader( CompileShader( ps_4_0_level_9_3, SolidColorShader() ) );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,211 @@
|
|||
/* -*- 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_LAYERMANAGERD3D10_H
|
||||
#define GFX_LAYERMANAGERD3D10_H
|
||||
|
||||
#include "Layers.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <d3d10_1.h>
|
||||
|
||||
#include "gfxContext.h"
|
||||
#include "nsIWidget.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
/**
|
||||
* This structure is used to pass rectangles to our shader constant. We can use
|
||||
* this for passing rectangular areas to SetVertexShaderConstant. In the format
|
||||
* of a 4 component float(x,y,width,height). Our vertex shader can then use
|
||||
* this to construct rectangular positions from the 0,0-1,1 quad that we source
|
||||
* it with.
|
||||
*/
|
||||
struct ShaderConstantRectD3D10
|
||||
{
|
||||
float mX, mY, mWidth, mHeight;
|
||||
ShaderConstantRectD3D10(float aX, float aY, float aWidth, float aHeight)
|
||||
: mX(aX), mY(aY), mWidth(aWidth), mHeight(aHeight)
|
||||
{ }
|
||||
|
||||
// For easy passing to SetVertexShaderConstantF.
|
||||
operator float* () { return &mX; }
|
||||
};
|
||||
|
||||
extern cairo_user_data_key_t gKeyD3D10Texture;
|
||||
|
||||
/*
|
||||
* This is the LayerManager used for Direct3D 9. For now this will render on
|
||||
* the main thread.
|
||||
*/
|
||||
class THEBES_API LayerManagerD3D10 : public LayerManager {
|
||||
public:
|
||||
LayerManagerD3D10(nsIWidget *aWidget);
|
||||
virtual ~LayerManagerD3D10();
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
bool Initialize();
|
||||
|
||||
/*
|
||||
* LayerManager implementation.
|
||||
*/
|
||||
virtual void SetRoot(Layer *aLayer);
|
||||
|
||||
void BeginTransaction();
|
||||
|
||||
void BeginTransactionWithTarget(gfxContext* aTarget);
|
||||
|
||||
struct CallbackInfo {
|
||||
DrawThebesLayerCallback Callback;
|
||||
void *CallbackData;
|
||||
};
|
||||
|
||||
void EndTransaction(DrawThebesLayerCallback aCallback,
|
||||
void* aCallbackData);
|
||||
|
||||
const CallbackInfo &GetCallbackInfo() { return mCurrentCallbackInfo; }
|
||||
|
||||
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 already_AddRefed<gfxASurface>
|
||||
CreateOptimalSurface(const gfxIntSize &aSize,
|
||||
gfxASurface::gfxImageFormat imageFormat);
|
||||
|
||||
virtual LayersBackend GetBackendType() { return LAYERS_D3D10; }
|
||||
virtual void GetBackendName(nsAString& name) { name.AssignLiteral("Direct3D 10"); }
|
||||
|
||||
#ifdef MOZ_LAYERS_HAVE_LOG
|
||||
virtual const char* Name() const { return "D3D9"; }
|
||||
#endif // MOZ_LAYERS_HAVE_LOG
|
||||
|
||||
// Public helpers
|
||||
|
||||
ID3D10Device1 *device() const { return mDevice; }
|
||||
|
||||
ID3D10Effect *effect() const { return mEffect; }
|
||||
|
||||
void SetViewport(const nsIntSize &aViewport);
|
||||
const nsIntSize &GetViewport() { return mViewport; }
|
||||
|
||||
private:
|
||||
void SetupPipeline();
|
||||
void UpdateRenderTarget();
|
||||
void VerifyBufferSize();
|
||||
|
||||
void Render();
|
||||
|
||||
nsRefPtr<ID3D10Device1> mDevice;
|
||||
|
||||
nsRefPtr<ID3D10Effect> mEffect;
|
||||
nsRefPtr<ID3D10InputLayout> mInputLayout;
|
||||
nsRefPtr<ID3D10Buffer> mVertexBuffer;
|
||||
|
||||
nsRefPtr<ID3D10RenderTargetView> mRTView;
|
||||
|
||||
nsRefPtr<IDXGISwapChain> mSwapChain;
|
||||
|
||||
nsIWidget *mWidget;
|
||||
|
||||
CallbackInfo mCurrentCallbackInfo;
|
||||
|
||||
nsIntSize mViewport;
|
||||
|
||||
/*
|
||||
* Context target, NULL when drawing directly to our swap chain.
|
||||
*/
|
||||
nsRefPtr<gfxContext> mTarget;
|
||||
|
||||
/*
|
||||
* Copies the content of our backbuffer to the set transaction target.
|
||||
*/
|
||||
void PaintToTarget();
|
||||
};
|
||||
|
||||
/*
|
||||
* General information and tree management for OGL layers.
|
||||
*/
|
||||
class LayerD3D10
|
||||
{
|
||||
public:
|
||||
LayerD3D10(LayerManagerD3D10 *aManager);
|
||||
|
||||
virtual LayerD3D10 *GetFirstChildD3D10() { return nsnull; }
|
||||
|
||||
void SetFirstChild(LayerD3D10 *aParent);
|
||||
|
||||
virtual Layer* GetLayer() = 0;
|
||||
|
||||
/**
|
||||
* This will render a child layer to whatever render target is currently
|
||||
* active. aOpacity and aTransform will pass any 'carried' transformations
|
||||
* and/or opacity from the parent. This allows the parent to avoid
|
||||
* rendering to intermediate surfaces when possible.
|
||||
*/
|
||||
virtual void RenderLayer(float aOpacity, const gfx3DMatrix &aTransform) = 0;
|
||||
virtual void Validate() {}
|
||||
|
||||
ID3D10Device1 *device() const { return mD3DManager->device(); }
|
||||
ID3D10Effect *effect() const { return mD3DManager->effect(); }
|
||||
|
||||
/* Called by the layer manager when it's destroyed */
|
||||
virtual void LayerManagerDestroyed() {}
|
||||
protected:
|
||||
LayerManagerD3D10 *mD3DManager;
|
||||
};
|
||||
|
||||
} /* layers */
|
||||
} /* mozilla */
|
||||
|
||||
#endif /* GFX_LAYERMANAGERD3D9_H */
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,339 @@
|
|||
/* -*- 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 "ThebesLayerD3D10.h"
|
||||
#include "gfxPlatform.h"
|
||||
|
||||
#include "gfxWindowsPlatform.h"
|
||||
#ifdef CAIRO_HAS_D2D_SURFACE
|
||||
#include "gfxD2DSurface.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
ThebesLayerD3D10::ThebesLayerD3D10(LayerManagerD3D10 *aManager)
|
||||
: ThebesLayer(aManager, NULL)
|
||||
, LayerD3D10(aManager)
|
||||
{
|
||||
mImplData = static_cast<LayerD3D10*>(this);
|
||||
}
|
||||
|
||||
ThebesLayerD3D10::~ThebesLayerD3D10()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Retention threshold - amount of pixels intersection required to enable
|
||||
* layer content retention. This is a guesstimate. Profiling could be done to
|
||||
* figure out the optimal threshold.
|
||||
*/
|
||||
#define RETENTION_THRESHOLD 16384
|
||||
|
||||
void
|
||||
ThebesLayerD3D10::SetVisibleRegion(const nsIntRegion &aRegion)
|
||||
{
|
||||
if (aRegion.IsEqual(mVisibleRegion)) {
|
||||
return;
|
||||
}
|
||||
|
||||
HRESULT hr;
|
||||
|
||||
nsIntRegion oldVisibleRegion = mVisibleRegion;
|
||||
ThebesLayer::SetVisibleRegion(aRegion);
|
||||
|
||||
if (!mTexture) {
|
||||
// If we don't need to retain content initialize lazily. This is good also
|
||||
// because we might get mIsOpaqueSurface set later than the first call to
|
||||
// SetVisibleRegion.
|
||||
return;
|
||||
}
|
||||
|
||||
VerifyContentType();
|
||||
|
||||
nsRefPtr<ID3D10Texture2D> oldTexture = mTexture;
|
||||
|
||||
nsIntRect oldBounds = oldVisibleRegion.GetBounds();
|
||||
nsIntRect newBounds = mVisibleRegion.GetBounds();
|
||||
|
||||
CreateNewTexture(gfxIntSize(newBounds.width, newBounds.height));
|
||||
|
||||
// Old visible region will become the region that is covered by both the
|
||||
// old and the new visible region.
|
||||
oldVisibleRegion.And(oldVisibleRegion, mVisibleRegion);
|
||||
// No point in retaining parts which were not valid.
|
||||
oldVisibleRegion.And(oldVisibleRegion, mValidRegion);
|
||||
|
||||
nsIntRect largeRect = oldVisibleRegion.GetLargestRectangle();
|
||||
|
||||
// If we had no hardware texture before or have no retained area larger than
|
||||
// the retention threshold, we're not retaining and are done here. If our
|
||||
// texture creation failed this can mean a device reset is pending and we
|
||||
// should silently ignore the failure. In the future when device failures
|
||||
// are properly handled we should test for the type of failure and gracefully
|
||||
// handle different failures. See bug 569081.
|
||||
if (!oldTexture || !mTexture ||
|
||||
largeRect.width * largeRect.height < RETENTION_THRESHOLD) {
|
||||
mValidRegion.SetEmpty();
|
||||
return;
|
||||
}
|
||||
|
||||
nsIntRegion retainedRegion;
|
||||
nsIntRegionRectIterator iter(oldVisibleRegion);
|
||||
const nsIntRect *r;
|
||||
while ((r = iter.Next())) {
|
||||
if (r->width * r->height > RETENTION_THRESHOLD) {
|
||||
// Calculate the retained rectangle's position on the old and the new
|
||||
// surface.
|
||||
D3D10_BOX box;
|
||||
box.left = r->x - oldBounds.x;
|
||||
box.top = r->y - oldBounds.y;
|
||||
box.right = box.left + r->width;
|
||||
box.bottom = box.top + r->height;
|
||||
box.back = 1.0f;
|
||||
box.front = 0;
|
||||
|
||||
device()->CopySubresourceRegion(mTexture, 0,
|
||||
r->x - newBounds.x,
|
||||
r->y - newBounds.y,
|
||||
0,
|
||||
oldTexture, 0,
|
||||
&box);
|
||||
|
||||
if (SUCCEEDED(hr)) {
|
||||
retainedRegion.Or(retainedRegion, *r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Areas which were valid and were retained are still valid
|
||||
mValidRegion.And(mValidRegion, retainedRegion);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ThebesLayerD3D10::InvalidateRegion(const nsIntRegion &aRegion)
|
||||
{
|
||||
mValidRegion.Sub(mValidRegion, aRegion);
|
||||
}
|
||||
|
||||
void
|
||||
ThebesLayerD3D10::RenderLayer(float aOpacity, const gfx3DMatrix &aTransform)
|
||||
{
|
||||
if (!mTexture) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsIntRect visibleRect = mVisibleRegion.GetBounds();
|
||||
|
||||
gfx3DMatrix transform = mTransform * aTransform;
|
||||
effect()->GetVariableByName("mLayerTransform")->SetRawValue(&transform._11, 0, 64);
|
||||
effect()->GetVariableByName("fLayerOpacity")->AsScalar()->SetFloat(GetOpacity() * aOpacity);
|
||||
|
||||
ID3D10EffectTechnique *technique;
|
||||
if (CanUseOpaqueSurface()) {
|
||||
technique = effect()->GetTechniqueByName("RenderRGBLayerPremul");
|
||||
} else {
|
||||
technique = effect()->GetTechniqueByName("RenderRGBALayerPremul");
|
||||
}
|
||||
|
||||
|
||||
nsIntRegionRectIterator iter(mVisibleRegion);
|
||||
|
||||
const nsIntRect *iterRect;
|
||||
if (mSRView) {
|
||||
effect()->GetVariableByName("tRGB")->AsShaderResource()->SetResource(mSRView);
|
||||
}
|
||||
|
||||
while ((iterRect = iter.Next())) {
|
||||
effect()->GetVariableByName("vLayerQuad")->AsVector()->SetFloatVector(
|
||||
ShaderConstantRectD3D10(
|
||||
(float)iterRect->x,
|
||||
(float)iterRect->y,
|
||||
(float)iterRect->width,
|
||||
(float)iterRect->height)
|
||||
);
|
||||
|
||||
effect()->GetVariableByName("vTextureCoords")->AsVector()->SetFloatVector(
|
||||
ShaderConstantRectD3D10(
|
||||
(float)(iterRect->x - visibleRect.x) / (float)visibleRect.width,
|
||||
(float)(iterRect->y - visibleRect.y) / (float)visibleRect.height,
|
||||
(float)iterRect->width / (float)visibleRect.width,
|
||||
(float)iterRect->height / (float)visibleRect.height)
|
||||
);
|
||||
|
||||
technique->GetPassByIndex(0)->Apply(0);
|
||||
device()->Draw(4, 0);
|
||||
}
|
||||
|
||||
// Set back to default.
|
||||
effect()->GetVariableByName("vTextureCoords")->AsVector()->
|
||||
SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f));
|
||||
}
|
||||
|
||||
void
|
||||
ThebesLayerD3D10::Validate()
|
||||
{
|
||||
if (mVisibleRegion.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
VerifyContentType();
|
||||
|
||||
nsIntRect visibleRect = mVisibleRegion.GetBounds();
|
||||
|
||||
if (!mTexture) {
|
||||
CreateNewTexture(gfxIntSize(visibleRect.width, visibleRect.height));
|
||||
mValidRegion.SetEmpty();
|
||||
}
|
||||
|
||||
if (!mValidRegion.IsEqual(mVisibleRegion)) {
|
||||
/* We use the bounds of the visible region because we draw the bounds of
|
||||
* this region when we draw this entire texture. We have to make sure that
|
||||
* the areas that aren't filled with content get their background drawn.
|
||||
* This is an issue for opaque surfaces, which otherwise won't get their
|
||||
* background painted.
|
||||
*/
|
||||
nsIntRegion region;
|
||||
region.Sub(mVisibleRegion, mValidRegion);
|
||||
|
||||
DrawRegion(region);
|
||||
|
||||
mValidRegion = mVisibleRegion;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ThebesLayerD3D10::LayerManagerDestroyed()
|
||||
{
|
||||
mD3DManager = nsnull;
|
||||
}
|
||||
|
||||
Layer*
|
||||
ThebesLayerD3D10::GetLayer()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
void
|
||||
ThebesLayerD3D10::VerifyContentType()
|
||||
{
|
||||
if (mD2DSurface) {
|
||||
gfxASurface::gfxContentType type = CanUseOpaqueSurface() ?
|
||||
gfxASurface::CONTENT_COLOR : gfxASurface::CONTENT_COLOR_ALPHA;
|
||||
|
||||
if (type != mD2DSurface->GetContentType()) {
|
||||
mD2DSurface = new gfxD2DSurface(mTexture, type);
|
||||
|
||||
if (!mD2DSurface || mD2DSurface->CairoStatus()) {
|
||||
NS_WARNING("Failed to create surface for ThebesLayerD3D10.");
|
||||
mD2DSurface = nsnull;
|
||||
return;
|
||||
}
|
||||
mValidRegion.SetEmpty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ThebesLayerD3D10::DrawRegion(const nsIntRegion &aRegion)
|
||||
{
|
||||
HRESULT hr;
|
||||
nsIntRect visibleRect = mVisibleRegion.GetBounds();
|
||||
|
||||
if (!mD2DSurface) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<gfxContext> context = new gfxContext(mD2DSurface);
|
||||
|
||||
nsIntRegionRectIterator iter(aRegion);
|
||||
context->Translate(gfxPoint(-visibleRect.x, -visibleRect.y));
|
||||
context->NewPath();
|
||||
const nsIntRect *iterRect;
|
||||
while ((iterRect = iter.Next())) {
|
||||
context->Rectangle(gfxRect(iterRect->x, iterRect->y, iterRect->width, iterRect->height));
|
||||
}
|
||||
context->Clip();
|
||||
|
||||
if (mD2DSurface->GetContentType() != gfxASurface::CONTENT_COLOR) {
|
||||
context->SetOperator(gfxContext::OPERATOR_CLEAR);
|
||||
context->Paint();
|
||||
context->SetOperator(gfxContext::OPERATOR_OVER);
|
||||
}
|
||||
|
||||
LayerManagerD3D10::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo();
|
||||
cbInfo.Callback(this, context, aRegion, nsIntRegion(), cbInfo.CallbackData);
|
||||
}
|
||||
|
||||
void
|
||||
ThebesLayerD3D10::CreateNewTexture(const gfxIntSize &aSize)
|
||||
{
|
||||
if (aSize.width == 0 || aSize.height == 0) {
|
||||
// Nothing to do.
|
||||
return;
|
||||
}
|
||||
|
||||
CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, aSize.width, aSize.height, 1, 1);
|
||||
desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
|
||||
desc.MiscFlags = D3D10_RESOURCE_MISC_GDI_COMPATIBLE;
|
||||
|
||||
HRESULT hr = device()->CreateTexture2D(&desc, NULL, getter_AddRefs(mTexture));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to create new texture for ThebesLayerD3D10!");
|
||||
return;
|
||||
}
|
||||
|
||||
hr = device()->CreateShaderResourceView(mTexture, NULL, getter_AddRefs(mSRView));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
NS_WARNING("Failed to create shader resource view for ThebesLayerD3D10.");
|
||||
}
|
||||
|
||||
mD2DSurface = new gfxD2DSurface(mTexture, CanUseOpaqueSurface() ?
|
||||
gfxASurface::CONTENT_COLOR : gfxASurface::CONTENT_COLOR_ALPHA);
|
||||
|
||||
if (!mD2DSurface || mD2DSurface->CairoStatus()) {
|
||||
NS_WARNING("Failed to create surface for ThebesLayerD3D10.");
|
||||
mD2DSurface = nsnull;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace layers */
|
||||
} /* namespace mozilla */
|
|
@ -0,0 +1,88 @@
|
|||
/* -*- 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_THEBESLAYERD3D10_H
|
||||
#define GFX_THEBESLAYERD3D10_H
|
||||
|
||||
#include "Layers.h"
|
||||
#include "LayerManagerD3D10.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class ThebesLayerD3D10 : public ThebesLayer,
|
||||
public LayerD3D10
|
||||
{
|
||||
public:
|
||||
ThebesLayerD3D10(LayerManagerD3D10 *aManager);
|
||||
virtual ~ThebesLayerD3D10();
|
||||
|
||||
/* Layer implementation */
|
||||
void SetVisibleRegion(const nsIntRegion& aRegion);
|
||||
|
||||
/* ThebesLayer implementation */
|
||||
void InvalidateRegion(const nsIntRegion& aRegion);
|
||||
|
||||
/* LayerD3D10 implementation */
|
||||
Layer* GetLayer();
|
||||
virtual void RenderLayer(float aOpacity, const gfx3DMatrix &aTransform);
|
||||
virtual void Validate();
|
||||
virtual void LayerManagerDestroyed();
|
||||
|
||||
private:
|
||||
/* Texture with our surface data */
|
||||
nsRefPtr<ID3D10Texture2D> mTexture;
|
||||
|
||||
/* Shader resource view for our texture */
|
||||
nsRefPtr<ID3D10ShaderResourceView> mSRView;
|
||||
|
||||
/* Checks if our D2D surface has the right content type */
|
||||
void VerifyContentType();
|
||||
|
||||
/* This contains the thebes surface */
|
||||
nsRefPtr<gfxASurface> mD2DSurface;
|
||||
|
||||
/* Have a region of our layer drawn */
|
||||
void DrawRegion(const nsIntRegion &aRegion);
|
||||
|
||||
/* Create a new texture */
|
||||
void CreateNewTexture(const gfxIntSize &aSize);
|
||||
};
|
||||
|
||||
} /* layers */
|
||||
} /* mozilla */
|
||||
#endif /* GFX_THEBESLAYERD3D10_H */
|
Загрузка…
Ссылка в новой задаче