Implement gl_PointCoord on SM3 hardware
TRAC #11594
Signed-off-by: Andrew Lewycky
Signed-off-by: Daniel Koch

Author:    Nicolas Capens

git-svn-id: https://angleproject.googlecode.com/svn/trunk@355 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/libEGL/Display.cpp b/src/libEGL/Display.cpp
index 287d8da..2c59bb3 100644
--- a/src/libEGL/Display.cpp
+++ b/src/libEGL/Display.cpp
@@ -362,6 +362,9 @@
         }
     }
 
+    // Permanent non-default states
+    mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE);
+
     Surface *surface = NULL;
 
     if (swapChain)
diff --git a/src/libGLESv2/Blit.cpp b/src/libGLESv2/Blit.cpp
index 92bde05..48b4034 100644
--- a/src/libGLESv2/Blit.cpp
+++ b/src/libGLESv2/Blit.cpp
@@ -232,12 +232,12 @@
 
 bool Blit::setVertexShader(ShaderId shader)
 {
-    return setShader<IDirect3DVertexShader9>(shader, mContext->getVertexShaderProfile(), &IDirect3DDevice9::CreateVertexShader, &IDirect3DDevice9::SetVertexShader);
+    return setShader<IDirect3DVertexShader9>(shader, mContext->supportsShaderModel3() ? "vs_3_0" : "vs_2_0", &IDirect3DDevice9::CreateVertexShader, &IDirect3DDevice9::SetVertexShader);
 }
 
 bool Blit::setPixelShader(ShaderId shader)
 {
-    return setShader<IDirect3DPixelShader9>(shader, mContext->getPixelShaderProfile(), &IDirect3DDevice9::CreatePixelShader, &IDirect3DDevice9::SetPixelShader);
+    return setShader<IDirect3DPixelShader9>(shader, mContext->supportsShaderModel3() ? "ps_3_0" : "ps_2_0", &IDirect3DDevice9::CreatePixelShader, &IDirect3DDevice9::SetPixelShader);
 }
 
 RECT Blit::getSurfaceRect(IDirect3DSurface9 *surface) const
diff --git a/src/libGLESv2/Context.cpp b/src/libGLESv2/Context.cpp
index 55a83ff..2257ed6 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -269,16 +269,7 @@
         depthStencil->Release();
     }
     
-    if (mDeviceCaps.PixelShaderVersion == D3DPS_VERSION(3, 0))
-    {
-        mPsProfile = "ps_3_0";
-        mVsProfile = "vs_3_0";
-    }
-    else  // egl::Display guarantees support for at least 2.0
-    {
-        mPsProfile = "ps_2_0";
-        mVsProfile = "vs_2_0";
-    }
+    mSupportsShaderModel3 = mDeviceCaps.PixelShaderVersion == D3DPS_VERSION(3, 0);
 
     markAllStateDirty();
 }
@@ -1283,7 +1274,7 @@
         break;
       case GL_ALIASED_POINT_SIZE_RANGE:
         params[0] = gl::ALIASED_POINT_SIZE_RANGE_MIN;
-        params[1] = gl::ALIASED_POINT_SIZE_RANGE_MAX;
+        params[1] = supportsShaderModel3() ? gl::ALIASED_POINT_SIZE_RANGE_MAX_SM3 : gl::ALIASED_POINT_SIZE_RANGE_MAX_SM2;
         break;
       case GL_DEPTH_RANGE:
         params[0] = mState.zNear;
@@ -2742,14 +2733,9 @@
     return GL_NO_ERROR;
 }
 
-const char *Context::getPixelShaderProfile()
+bool Context::supportsShaderModel3() const
 {
-    return mPsProfile;
-}
-
-const char *Context::getVertexShaderProfile()
-{
-    return mVsProfile;
+    return mSupportsShaderModel3;
 }
 
 void Context::detachBuffer(GLuint buffer)
diff --git a/src/libGLESv2/Context.h b/src/libGLESv2/Context.h
index 913fae2..2025278 100644
--- a/src/libGLESv2/Context.h
+++ b/src/libGLESv2/Context.h
@@ -67,7 +67,8 @@
 const float ALIASED_LINE_WIDTH_RANGE_MIN = 1.0f;
 const float ALIASED_LINE_WIDTH_RANGE_MAX = 1.0f;
 const float ALIASED_POINT_SIZE_RANGE_MIN = 1.0f;
-const float ALIASED_POINT_SIZE_RANGE_MAX = 1.0f;
+const float ALIASED_POINT_SIZE_RANGE_MAX_SM2 = 1.0f;
+const float ALIASED_POINT_SIZE_RANGE_MAX_SM3 = 64.0f;
 
 enum SamplerType
 {
@@ -373,9 +374,7 @@
 
     GLenum getError();
 
-    const char *getPixelShaderProfile();
-    const char *getVertexShaderProfile();
-
+    bool supportsShaderModel3() const;
     const char *getExtensionString() const;
 
     Blit *getBlitter() { return mBlit; }
@@ -451,8 +450,7 @@
     unsigned int mAppliedRenderTargetSerial;
     unsigned int mAppliedDepthbufferSerial;
 
-    const char *mPsProfile;
-    const char *mVsProfile;
+    bool mSupportsShaderModel3;
 
     // state caching flags
     bool mClearStateDirty;
diff --git a/src/libGLESv2/Program.cpp b/src/libGLESv2/Program.cpp
index 78253c7..eceab16 100644
--- a/src/libGLESv2/Program.cpp
+++ b/src/libGLESv2/Program.cpp
@@ -1195,6 +1195,10 @@
         }
     }
 
+    Context *context = getContext();
+    bool sm3 = context->supportsShaderModel3();
+    std::string varyingSemantic = (sm3 ? "COLOR" : "TEXCOORD");
+
     mVertexHLSL += "struct VS_INPUT\n"
                    "{\n";
 
@@ -1228,12 +1232,17 @@
     {
         int registerSize = packing[r][3] ? 4 : (packing[r][2] ? 3 : (packing[r][1] ? 2 : 1));
 
-        mVertexHLSL += "    float" + str(registerSize) + " v" + str(r) + " : TEXCOORD" + str(r) + ";\n";
+        mVertexHLSL += "    float" + str(registerSize) + " v" + str(r) + " : " + varyingSemantic + str(r) + ";\n";
     }
 
     if (mFragmentShader->mUsesFragCoord)
     {
-        mVertexHLSL += "    float4 gl_FragCoord : TEXCOORD" + str(registers) + ";\n";
+        mVertexHLSL += "    float4 gl_FragCoord : " + varyingSemantic + str(registers) + ";\n";
+    }
+
+    if (mVertexShader->mUsesPointSize && sm3)
+    {
+        mVertexHLSL += "    float gl_PointSize : PSIZE;\n";
     }
 
     mVertexHLSL += "};\n"
@@ -1262,6 +1271,11 @@
                    "    output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
                    "    output.gl_Position.w = gl_Position.w;\n";
 
+    if (mVertexShader->mUsesPointSize && sm3)
+    {
+        mVertexHLSL += "    output.gl_PointSize = clamp(gl_PointSize, 1.0, " + str((int)ALIASED_POINT_SIZE_RANGE_MAX_SM3) + ");\n";
+    }
+
     if (mFragmentShader->mUsesFragCoord)
     {
         mVertexHLSL += "    output.gl_FragCoord = gl_Position;\n";
@@ -1345,7 +1359,7 @@
                 for (int j = 0; j < rows; j++)
                 {
                     std::string n = str(varying->reg + i * rows + j);
-                    mPixelHLSL += "    float4 v" + n + " : TEXCOORD" + n + ";\n";
+                    mPixelHLSL += "    float4 v" + n + " : " + varyingSemantic + n + ";\n";
                 }
             }
         }
@@ -1354,9 +1368,14 @@
 
     if (mFragmentShader->mUsesFragCoord)
     {
-        mPixelHLSL += "    float4 gl_FragCoord : TEXCOORD" + str(registers) + ";\n";
+        mPixelHLSL += "    float4 gl_FragCoord : " + varyingSemantic + str(registers) + ";\n";
     }
-        
+
+    if (mFragmentShader->mUsesPointCoord && sm3)
+    {
+        mPixelHLSL += "    float2 gl_PointCoord : TEXCOORD0;\n";
+    }
+
     if (mFragmentShader->mUsesFrontFacing)
     {
         mPixelHLSL += "    float vFace : VFACE;\n";
@@ -1381,6 +1400,11 @@
                       "    gl_FragCoord.w = rhw;\n";
     }
 
+    if (mFragmentShader->mUsesPointCoord && sm3)
+    {
+        mPixelHLSL += "    gl_PointCoord = float2(input.gl_PointCoord.x, 1.0 - input.gl_PointCoord.y);\n";
+    }
+
     if (mFragmentShader->mUsesFrontFacing)
     {
         mPixelHLSL += "    gl_FrontFacing = dx_PointsOrLines || (dx_FrontCCW ? (input.vFace >= 0.0) : (input.vFace <= 0.0));\n";
@@ -1447,10 +1471,6 @@
         return;
     }
 
-    Context *context = getContext();
-    const char *vertexProfile = context->getVertexShaderProfile();
-    const char *pixelProfile = context->getPixelShaderProfile();
-
     mPixelHLSL = mFragmentShader->getHLSL();
     mVertexHLSL = mVertexShader->getHLSL();
 
@@ -1459,6 +1479,10 @@
         return;
     }
 
+    Context *context = getContext();
+    const char *vertexProfile = context->supportsShaderModel3() ? "vs_3_0" : "vs_2_0";
+    const char *pixelProfile = context->supportsShaderModel3() ? "ps_3_0" : "ps_2_0";
+
     ID3DXBuffer *vertexBinary = compileToBinary(mVertexHLSL.c_str(), vertexProfile, &mConstantTableVS);
     ID3DXBuffer *pixelBinary = compileToBinary(mPixelHLSL.c_str(), pixelProfile, &mConstantTablePS);
 
diff --git a/src/libGLESv2/Shader.cpp b/src/libGLESv2/Shader.cpp
index 730c1b5..13d7ea7 100644
--- a/src/libGLESv2/Shader.cpp
+++ b/src/libGLESv2/Shader.cpp
@@ -262,6 +262,8 @@
 
         mUsesFragCoord = strstr(mHlsl, "GL_USES_FRAG_COORD") != NULL;
         mUsesFrontFacing = strstr(mHlsl, "GL_USES_FRONT_FACING") != NULL;
+        mUsesPointSize = strstr(mHlsl, "GL_USES_POINT_SIZE") != NULL;
+        mUsesPointCoord = strstr(mHlsl, "GL_USES_POINT_COORD") != NULL;
     }
 }
 
diff --git a/src/libGLESv2/Shader.h b/src/libGLESv2/Shader.h
index 777c236..649fa9f 100644
--- a/src/libGLESv2/Shader.h
+++ b/src/libGLESv2/Shader.h
@@ -93,6 +93,8 @@
 
     bool mUsesFragCoord;
     bool mUsesFrontFacing;
+    bool mUsesPointSize;
+    bool mUsesPointCoord;
 
     Context *mContext;