Import changes from an internal repo.
authorJarkko Pöyry <jpoyry@google.com>
Tue, 30 Sep 2014 21:56:09 +0000 (14:56 -0700)
committerJarkko Pöyry <jpoyry@google.com>
Tue, 30 Sep 2014 21:56:09 +0000 (14:56 -0700)
* Fix broken clipping result
* Fix invalid format-type pair in readPixels()

Change-Id: I996a9c5b340ae4d455219e57ff16d2b1456b015c

framework/referencerenderer/rrRenderer.cpp
modules/gles31/functional/es31fTextureGatherTests.cpp

index e18615a..dc6ec31 100644 (file)
@@ -245,11 +245,19 @@ ClipVec4 ComponentPlane<Sign, CompNdx>::getLineIntersectionPoint (const ClipVec4
        // A point on line might be far away, causing clipping ratio (clipLineSegmentEnd) to become extremely close to 1.0
        // even if the another point is not on the plane. Prevent clipping ratio from saturating by using points on line
        // that are (nearly) on this and (nearly) on the opposite plane.
-       const ClipVec4 clippedV0 = tcu::mix(v0, v1, ComponentPlane<+1, CompNdx>().clipLineSegmentEnd(v0, v1));
-       const ClipVec4 clippedV1 = tcu::mix(v0, v1, ComponentPlane<-1, CompNdx>().clipLineSegmentEnd(v0, v1));
 
-       // Find intersection point of line from v0 to v1 and the current plane.
-       return tcu::mix(clippedV0, clippedV1, clipLineSegmentEnd(clippedV0, clippedV1));
+       const ClipVec4  clippedV0       = tcu::mix(v0, v1, ComponentPlane<+1, CompNdx>().clipLineSegmentEnd(v0, v1));
+       const ClipVec4  clippedV1       = tcu::mix(v0, v1, ComponentPlane<-1, CompNdx>().clipLineSegmentEnd(v0, v1));
+       const ClipFloat clipRatio       = clipLineSegmentEnd(clippedV0, clippedV1);
+
+       // Find intersection point of line from v0 to v1 and the current plane. Avoid ratios near 1.0
+       if (clipRatio <= (ClipFloat)0.5)
+               return tcu::mix(clippedV0, clippedV1, clipRatio);
+       else
+       {
+               const ClipFloat complementClipRatio = clipLineSegmentEnd(clippedV1, clippedV0);
+               return tcu::mix(clippedV1, clippedV0, complementClipRatio);
+       }
 }
 
 struct TriangleVertex
@@ -273,12 +281,11 @@ void clipTriangleOneVertex (std::vector<TriangleVertex>& clippedEdges, const Cli
        bool                    outputDegenerate = false;
 
        {
-               const TriangleVertex& inside    = v1;
-               const TriangleVertex& outside   = clipped;
-                     TriangleVertex& middle    = mid1;
+               const TriangleVertex&   inside  = v1;
+               const TriangleVertex&   outside = clipped;
+                     TriangleVertex&   middle  = mid1;
 
-               const ClipFloat hitDist = plane.clipLineSegmentEnd(inside.position, outside.position);
-               DE_ASSERT(hitDist >= (ClipFloat)0.0);
+               const ClipFloat                 hitDist = plane.clipLineSegmentEnd(inside.position, outside.position);
 
                if (hitDist >= degenerateLimit)
                {
@@ -298,12 +305,11 @@ void clipTriangleOneVertex (std::vector<TriangleVertex>& clippedEdges, const Cli
        }
 
        {
-               const TriangleVertex& inside = v2;
-               const TriangleVertex& outside = clipped;
-                     TriangleVertex& middle = mid2;
+               const TriangleVertex&   inside  = v2;
+               const TriangleVertex&   outside = clipped;
+                     TriangleVertex&   middle  = mid2;
 
-               const ClipFloat hitDist = plane.clipLineSegmentEnd(inside.position, outside.position);
-               DE_ASSERT(hitDist >= (ClipFloat)0.0);
+               const ClipFloat                 hitDist = plane.clipLineSegmentEnd(inside.position, outside.position);
 
                if (hitDist >= degenerateLimit)
                {
@@ -341,25 +347,25 @@ void clipTriangleOneVertex (std::vector<TriangleVertex>& clippedEdges, const Cli
 
 void clipTriangleTwoVertices (std::vector<TriangleVertex>& clippedEdges, const ClipVolumePlane& plane, const TriangleVertex& v0, const TriangleVertex& clipped1, const TriangleVertex& clipped2)
 {
-       const ClipFloat degenerateLimit = (ClipFloat)1.0;
+       const ClipFloat unclippableLimit = (ClipFloat)1.0;
 
        // calc clip pos
        TriangleVertex  mid1;
        TriangleVertex  mid2;
-       bool                    outputDegenerate = false;
+       bool                    unclippableVertex1 = false;
+       bool                    unclippableVertex2 = false;
 
        {
-               const TriangleVertex& inside = v0;
-               const TriangleVertex& outside = clipped1;
-                     TriangleVertex& middle = mid1;
+               const TriangleVertex&   inside  = v0;
+               const TriangleVertex&   outside = clipped1;
+                     TriangleVertex&   middle  = mid1;
 
-               const ClipFloat hitDist = plane.clipLineSegmentEnd(inside.position, outside.position);
-               DE_ASSERT(hitDist >= (ClipFloat)0.0);
+               const ClipFloat                 hitDist = plane.clipLineSegmentEnd(inside.position, outside.position);
 
-               if (hitDist >= degenerateLimit)
+               if (hitDist >= unclippableLimit)
                {
-                       // do not generate degenerate triangles
-                       outputDegenerate = true;
+                       // this edge cannot be clipped because the edge is really close to the volume boundary
+                       unclippableVertex1 = true;
                }
                else
                {
@@ -374,17 +380,16 @@ void clipTriangleTwoVertices (std::vector<TriangleVertex>& clippedEdges, const C
        }
 
        {
-               const TriangleVertex& inside = v0;
-               const TriangleVertex& outside = clipped2;
-                     TriangleVertex& middle = mid2;
+               const TriangleVertex&   inside  = v0;
+               const TriangleVertex&   outside = clipped2;
+                     TriangleVertex&   middle  = mid2;
 
-               const ClipFloat hitDist = plane.clipLineSegmentEnd(inside.position, outside.position);
-               DE_ASSERT(hitDist >= (ClipFloat)0.0);
+               const ClipFloat                 hitDist = plane.clipLineSegmentEnd(inside.position, outside.position);
 
-               if (hitDist >= degenerateLimit)
+               if (hitDist >= unclippableLimit)
                {
-                       // do not generate degenerate triangles
-                       outputDegenerate = true;
+                       // this edge cannot be clipped because the edge is really close to the volume boundary
+                       unclippableVertex2 = true;
                }
                else
                {
@@ -398,13 +403,27 @@ void clipTriangleTwoVertices (std::vector<TriangleVertex>& clippedEdges, const C
                }
        }
 
-       if (!outputDegenerate)
+       if (!unclippableVertex1 && !unclippableVertex2)
        {
                // gen triangle (v0) -> mid1 -> mid2
                clippedEdges.push_back(v0);
                clippedEdges.push_back(mid1);
                clippedEdges.push_back(mid2);
        }
+       else if (!unclippableVertex1 && unclippableVertex2)
+       {
+               // clip just vertex 1
+               clippedEdges.push_back(v0);
+               clippedEdges.push_back(mid1);
+               clippedEdges.push_back(clipped2);
+       }
+       else if (unclippableVertex1 && !unclippableVertex2)
+       {
+               // clip just vertex 2
+               clippedEdges.push_back(v0);
+               clippedEdges.push_back(clipped1);
+               clippedEdges.push_back(mid2);
+       }
        else
        {
                // don't modify
@@ -593,7 +612,7 @@ void clipPrimitives (std::vector<pa::Triangle>&             list,
                                {
                                        std::vector<TriangleVertex> convexPrimitive;
 
-                                       // Clip triangle and form a convex n-gon ( n c {2, 3} )
+                                       // Clip triangle and form a convex n-gon ( n c {3, 4} )
                                        clipTriangleToPlane(convexPrimitive, subTriangles[subTriangleNdx].vertices, *planes[planeNdx]);
 
                                        // Subtriangle completely discarded
index 78dc85d..a35444c 100644 (file)
@@ -104,13 +104,6 @@ static void fillWithRandomColorTiles (const PixelBufferAccess& dst, const Vec4&
        }
 }
 
-static tcu::TextureLevel getPixels (const glu::RenderContext& renderCtx, const IVec2& size, const tcu::TextureFormat& colorBufferFormat)
-{
-       tcu::TextureLevel result(colorBufferFormat, size.x(), size.y());
-       glu::readPixels(renderCtx, 0, 0, result.getAccess());
-       return result;
-}
-
 static inline bool isDepthFormat (const tcu::TextureFormat& fmt)
 {
        return fmt.order == tcu::TextureFormat::D || fmt.order == tcu::TextureFormat::DS;
@@ -137,6 +130,42 @@ static inline bool isUIntFormatType (tcu::TextureFormat::ChannelType type)
                   type == tcu::TextureFormat::UNSIGNED_INT32;
 }
 
+static tcu::TextureLevel getPixels (const glu::RenderContext& renderCtx, const IVec2& size, const tcu::TextureFormat& colorBufferFormat)
+{
+       tcu::TextureLevel result(colorBufferFormat, size.x(), size.y());
+
+       // only a few pixel formats are guaranteed to be valid targets for readPixels, convert the rest
+       if (colorBufferFormat.order == tcu::TextureFormat::RGBA &&
+               (colorBufferFormat.type == tcu::TextureFormat::UNORM_INT8       ||
+                colorBufferFormat.type == tcu::TextureFormat::SIGNED_INT32     ||
+                colorBufferFormat.type == tcu::TextureFormat::UNSIGNED_INT32))
+       {
+               // valid as is
+               glu::readPixels(renderCtx, 0, 0, result.getAccess());
+       }
+       else if (colorBufferFormat.order == tcu::TextureFormat::RGBA &&
+                        (isSIntFormatType(colorBufferFormat.type) ||
+                         isUIntFormatType(colorBufferFormat.type)))
+       {
+               // signed and unsigned integers must be read using 32-bit values
+               const bool                      isSigned        = isSIntFormatType(colorBufferFormat.type);
+               tcu::TextureLevel       readResult      (tcu::TextureFormat(tcu::TextureFormat::RGBA,
+                                                                                                                   (isSigned) ? (tcu::TextureFormat::SIGNED_INT32) : (tcu::TextureFormat::UNSIGNED_INT32)),
+                                                                                size.x(),
+                                                                                size.y());
+
+               glu::readPixels(renderCtx, 0, 0, readResult.getAccess());
+               tcu::copy(result.getAccess(), readResult.getAccess());
+       }
+       else
+       {
+               // unreadable format
+               DE_ASSERT(false);
+       }
+
+       return result;
+}
+
 enum TextureSwizzleComponent
 {
        TEXTURESWIZZLECOMPONENT_R = 0,