Attempt to ensure pipeline flush on rendertarget change
Some ATI cards appear not to flush the pipeline correctly, causing textures not to pick up newly-drawn contexts, so do an extra no-op draw when necessary.
BUG=169
TEST=chromium on hulu.com
Review URL: http://codereview.appspot.com/4576051
git-svn-id: http://angleproject.googlecode.com/svn/trunk@693 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/common/version.h b/src/common/version.h
index 8a075e9..b7ebb8f 100644
--- a/src/common/version.h
+++ b/src/common/version.h
@@ -1,7 +1,7 @@
#define MAJOR_VERSION 0
#define MINOR_VERSION 0
#define BUILD_VERSION 0
-#define BUILD_REVISION 692
+#define BUILD_REVISION 693
#define STRINGIFY(x) #x
#define MACRO_STRINGIFY(x) STRINGIFY(x)
diff --git a/src/libEGL/Display.cpp b/src/libEGL/Display.cpp
index b8b5e2f..1d64f9a 100644
--- a/src/libEGL/Display.cpp
+++ b/src/libEGL/Display.cpp
@@ -141,6 +141,8 @@
if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE) {mMinSwapInterval = std::min(mMinSwapInterval, 3); mMaxSwapInterval = std::max(mMaxSwapInterval, 3);}
if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR) {mMinSwapInterval = std::min(mMinSwapInterval, 4); mMaxSwapInterval = std::max(mMaxSwapInterval, 4);}
+ mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier);
+
const D3DFORMAT renderTargetFormats[] =
{
D3DFMT_A1R5G5B5,
@@ -688,6 +690,11 @@
return mDeviceCaps;
}
+D3DADAPTER_IDENTIFIER9 *Display::getAdapterIdentifier()
+{
+ return &mAdapterIdentifier;
+}
+
bool Display::isDeviceLost()
{
if (mDeviceEx)
diff --git a/src/libEGL/Display.h b/src/libEGL/Display.h
index f377db4..86de5cd 100644
--- a/src/libEGL/Display.h
+++ b/src/libEGL/Display.h
@@ -60,6 +60,7 @@
virtual IDirect3DDevice9 *getDevice();
virtual D3DCAPS9 getDeviceCaps();
+ virtual D3DADAPTER_IDENTIFIER9 *getAdapterIdentifier();
bool isDeviceLost();
virtual void getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray);
virtual bool getCompressedTextureSupport();
@@ -91,6 +92,7 @@
IDirect3DDevice9 *mDevice;
IDirect3DDevice9Ex *mDeviceEx; // Might be null if D3D9Ex is not supported.
D3DCAPS9 mDeviceCaps;
+ D3DADAPTER_IDENTIFIER9 mAdapterIdentifier;
HWND mDeviceWindow;
bool mSceneStarted;
diff --git a/src/libGLESv2/Context.cpp b/src/libGLESv2/Context.cpp
index 1c66450..6c973ea 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -1737,6 +1737,15 @@
GLint alwaysFront = !isTriangleMode(drawMode);
programObject->setUniform1iv(pointsOrLines, 1, &alwaysFront);
+ egl::Display *display = getDisplay();
+ D3DADAPTER_IDENTIFIER9 *identifier = display->getAdapterIdentifier();
+ bool zeroColorMaskAllowed = identifier->VendorId != 0x1002;
+ // Apparently some ATI cards have a bug where a draw with a zero color
+ // write mask can cause later draws to have incorrect results. Instead,
+ // set a nonzero color write mask but modify the blend state so that no
+ // drawing is done.
+ // http://code.google.com/p/angleproject/issues/detail?id=169
+
if (mCullStateDirty || mFrontFaceDirty)
{
if (mState.cullFace)
@@ -1766,6 +1775,12 @@
mDepthStateDirty = false;
}
+ if (!zeroColorMaskAllowed && (mMaskStateDirty || mBlendStateDirty))
+ {
+ mBlendStateDirty = true;
+ mMaskStateDirty = true;
+ }
+
if (mBlendStateDirty)
{
if (mState.blend)
@@ -1874,8 +1889,22 @@
if (mMaskStateDirty)
{
- device->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen,
- mState.colorMaskBlue, mState.colorMaskAlpha));
+ int colorMask = es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen,
+ mState.colorMaskBlue, mState.colorMaskAlpha);
+ if (colorMask == 0 && !zeroColorMaskAllowed)
+ {
+ // Enable green channel, but set blending so nothing will be drawn.
+ device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_GREEN);
+ device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
+
+ device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
+ device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
+ device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
+ }
+ else
+ {
+ device->SetRenderState(D3DRS_COLORWRITEENABLE, colorMask);
+ }
device->SetRenderState(D3DRS_ZWRITEENABLE, mState.depthMask ? TRUE : FALSE);
mMaskStateDirty = false;