Recommit r2584 with gpu pass of the new ReadPixels test disabled in fixed pt (gpu code doesn't work in general in fixed pt).



git-svn-id: http://skia.googlecode.com/svn/trunk@2586 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/tests/ReadPixelsTest.cpp b/tests/ReadPixelsTest.cpp
new file mode 100644
index 0000000..c39e03b
--- /dev/null
+++ b/tests/ReadPixelsTest.cpp
@@ -0,0 +1,266 @@
+
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "Test.h"
+#include "SkCanvas.h"
+#include "SkRegion.h"
+#include "SkGpuDevice.h"
+
+
+static const int DEV_W = 100, DEV_H = 100;
+static const SkIRect DEV_RECT = SkIRect::MakeWH(DEV_W, DEV_H);
+static const SkRect DEV_RECT_S = SkRect::MakeWH(DEV_W * SK_Scalar1, 
+                                                DEV_H * SK_Scalar1);
+
+namespace {
+SkPMColor getCanvasColor(int x, int y) {
+    SkASSERT(x >= 0 && x < DEV_W);
+    SkASSERT(y >= 0 && y < DEV_H);
+    return SkPackARGB32(0xff, x, y, 0x0);
+}
+    
+SkPMColor getBitmapColor(int x, int y, int w, int h) {
+    int n = y * w + x;
+    
+    U8CPU b = n & 0xff;
+    U8CPU g = (n >> 8) & 0xff;
+    U8CPU r = (n >> 16) & 0xff;
+    return SkPackARGB32(0xff, r, g , b);
+}
+
+void fillCanvas(SkCanvas* canvas) {
+    static SkBitmap bmp;
+    if (bmp.isNull()) {
+        bmp.setConfig(SkBitmap::kARGB_8888_Config, DEV_W, DEV_H);
+        bool alloc = bmp.allocPixels();
+        SkASSERT(alloc);
+        SkAutoLockPixels alp(bmp);
+        intptr_t pixels = reinterpret_cast<intptr_t>(bmp.getPixels());
+        for (int y = 0; y < DEV_H; ++y) {
+            for (int x = 0; x < DEV_W; ++x) {
+                SkPMColor* pixel = reinterpret_cast<SkPMColor*>(pixels + y * bmp.rowBytes() + x * bmp.bytesPerPixel());
+                *pixel = getCanvasColor(x, y);
+            }
+        }
+    }
+    canvas->save();
+    canvas->setMatrix(SkMatrix::I());
+    canvas->clipRect(DEV_RECT_S, SkRegion::kReplace_Op);
+    SkPaint paint;
+    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+    canvas->drawBitmap(bmp, 0, 0, &paint);
+    canvas->restore();
+}
+    
+void fillBitmap(SkBitmap* bitmap) {
+    SkASSERT(bitmap->lockPixelsAreWritable());
+    SkAutoLockPixels alp(*bitmap);
+    int w = bitmap->width();
+    int h = bitmap->height();
+    intptr_t pixels = reinterpret_cast<intptr_t>(bitmap->getPixels());
+    for (int y = 0; y < h; ++y) {
+        for (int x = 0; x < w; ++x) {
+            SkPMColor* pixel = reinterpret_cast<SkPMColor*>(pixels + y * bitmap->rowBytes() + x * bitmap->bytesPerPixel());
+            *pixel = getBitmapColor(x, y, w, h);
+        }
+    }
+}
+
+// checks the bitmap contains correct pixels after the readPixels
+// if the bitmap was prefilled with pixels it checks that these weren't
+// overwritten in the area outside the readPixels.
+bool checkRead(skiatest::Reporter* reporter,
+               const SkBitmap& bitmap,
+               int x, int y,
+               bool preFilledBmp) {
+    SkASSERT(SkBitmap::kARGB_8888_Config == bitmap.config());
+    SkASSERT(!bitmap.isNull());
+    
+    int bw = bitmap.width();
+    int bh = bitmap.height();
+
+    SkIRect srcRect = SkIRect::MakeXYWH(x, y, bw, bh);
+    SkIRect clippedSrcRect = DEV_RECT;
+    if (!clippedSrcRect.intersect(srcRect)) {
+        clippedSrcRect.setEmpty();
+    }
+
+    SkAutoLockPixels alp(bitmap);
+    intptr_t pixels = reinterpret_cast<intptr_t>(bitmap.getPixels());
+    for (int by = 0; by < bh; ++by) {
+        for (int bx = 0; bx < bw; ++bx) {
+            int devx = bx + srcRect.fLeft;
+            int devy = by + srcRect.fTop;
+            
+            SkPMColor pixel = *reinterpret_cast<SkPMColor*>(pixels + by * bitmap.rowBytes() + bx * bitmap.bytesPerPixel());
+
+            if (clippedSrcRect.contains(devx, devy)) {
+                REPORTER_ASSERT(reporter, getCanvasColor(devx, devy) == pixel);
+                if (getCanvasColor(devx, devy) != pixel) {
+                    return false;
+                }
+            } else if (preFilledBmp) {
+                REPORTER_ASSERT(reporter, getBitmapColor(bx, by, bw, bh) == pixel);
+                if (getBitmapColor(bx, by, bw, bh) != pixel) {
+                    return false;
+                }
+            }
+        }
+    }
+    return true;
+}
+
+enum BitmapInit {
+    kFirstBitmapInit = 0,
+    
+    kNoPixels_BitmapInit = kFirstBitmapInit,
+    kTight_BitmapInit,
+    kRowBytes_BitmapInit,
+    
+    kBitmapInitCnt
+};
+
+BitmapInit nextBMI(BitmapInit bmi) {
+    int x = bmi;
+    return static_cast<BitmapInit>(++x);
+}
+
+
+void init_bitmap(SkBitmap* bitmap, const SkIRect& rect, BitmapInit init) {
+    int w = rect.width();
+    int h = rect.height();
+    int rowBytes = 0;
+    bool alloc = true;
+    switch (init) {
+        case kNoPixels_BitmapInit:
+            alloc = false;
+        case kTight_BitmapInit:
+            break;
+        case kRowBytes_BitmapInit:
+            rowBytes = w * sizeof(SkPMColor) + 16 * sizeof(SkPMColor);
+            break;
+        default:
+            SkASSERT(0);
+            break;
+    }
+    bitmap->setConfig(SkBitmap::kARGB_8888_Config, w, h, rowBytes);
+    if (alloc) {
+        bitmap->allocPixels();
+    }
+}
+
+void ReadPixelsTest(skiatest::Reporter* reporter, GrContext* context) {
+    SkCanvas canvas;
+    
+    const SkIRect testRects[] = {
+        // entire thing
+        DEV_RECT,
+        // larger on all sides
+        SkIRect::MakeLTRB(-10, -10, DEV_W + 10, DEV_H + 10),
+        // fully contained
+        SkIRect::MakeLTRB(DEV_W / 4, DEV_H / 4, 3 * DEV_W / 4, 3 * DEV_H / 4),
+        // outside top left
+        SkIRect::MakeLTRB(-10, -10, -1, -1),
+        // touching top left corner
+        SkIRect::MakeLTRB(-10, -10, 0, 0),
+        // overlapping top left corner
+        SkIRect::MakeLTRB(-10, -10, DEV_W / 4, DEV_H / 4),
+        // overlapping top left and top right corners
+        SkIRect::MakeLTRB(-10, -10, DEV_W  + 10, DEV_H / 4),
+        // touching entire top edge
+        SkIRect::MakeLTRB(-10, -10, DEV_W  + 10, 0),
+        // overlapping top right corner
+        SkIRect::MakeLTRB(3 * DEV_W / 4, -10, DEV_W  + 10, DEV_H / 4),
+        // contained in x, overlapping top edge
+        SkIRect::MakeLTRB(DEV_W / 4, -10, 3 * DEV_W  / 4, DEV_H / 4),
+        // outside top right corner
+        SkIRect::MakeLTRB(DEV_W + 1, -10, DEV_W + 10, -1),
+        // touching top right corner
+        SkIRect::MakeLTRB(DEV_W, -10, DEV_W + 10, 0),
+        // overlapping top left and bottom left corners
+        SkIRect::MakeLTRB(-10, -10, DEV_W / 4, DEV_H + 10),
+        // touching entire left edge
+        SkIRect::MakeLTRB(-10, -10, 0, DEV_H + 10),
+        // overlapping bottom left corner
+        SkIRect::MakeLTRB(-10, 3 * DEV_H / 4, DEV_W / 4, DEV_H + 10),
+        // contained in y, overlapping left edge
+        SkIRect::MakeLTRB(-10, DEV_H / 4, DEV_W / 4, 3 * DEV_H / 4),
+        // outside bottom left corner
+        SkIRect::MakeLTRB(-10, DEV_H + 1, -1, DEV_H + 10),
+        // touching bottom left corner
+        SkIRect::MakeLTRB(-10, DEV_H, 0, DEV_H + 10),
+        // overlapping bottom left and bottom right corners
+        SkIRect::MakeLTRB(-10, 3 * DEV_H / 4, DEV_W + 10, DEV_H + 10),
+        // touching entire left edge
+        SkIRect::MakeLTRB(0, DEV_H, DEV_W, DEV_H + 10),
+        // overlapping bottom right corner
+        SkIRect::MakeLTRB(3 * DEV_W / 4, 3 * DEV_H / 4, DEV_W + 10, DEV_H + 10),
+        // overlapping top right and bottom right corners
+        SkIRect::MakeLTRB(3 * DEV_W / 4, -10, DEV_W + 10, DEV_H + 10),
+    };
+
+    for (int dtype = 0; dtype < 2; ++dtype) {
+
+        if (0 == dtype) {
+            canvas.setDevice(new SkDevice(SkBitmap::kARGB_8888_Config, DEV_W, DEV_H, false))->unref();
+        } else {
+#if SK_SCALAR_IS_FIXED
+            // GPU device known not to work in the fixed pt build.
+            continue;
+#endif
+            canvas.setDevice(new SkGpuDevice(context, SkBitmap::kARGB_8888_Config, DEV_W, DEV_H))->unref();
+        }
+        fillCanvas(&canvas);
+
+        for (int rect = 0; rect < SK_ARRAY_COUNT(testRects); ++rect) {
+            SkBitmap bmp;
+            for (BitmapInit bmi = kFirstBitmapInit; bmi < kBitmapInitCnt; bmi = nextBMI(bmi)) {
+
+                const SkIRect& srcRect = testRects[rect];
+
+                init_bitmap(&bmp, srcRect, bmi);
+
+                // if the bitmap has pixels allocated before the readPixels, note
+                // that and fill them with pattern
+                bool startsWithPixels = !bmp.isNull();
+                if (startsWithPixels) {
+                    fillBitmap(&bmp);
+                }
+                
+                bool success = canvas.readPixels(&bmp, srcRect.fLeft, srcRect.fTop);
+                
+                // determine whether we expected the read to succeed.
+                REPORTER_ASSERT(reporter, success == SkIRect::Intersects(srcRect, DEV_RECT));
+
+                if (success || startsWithPixels) {
+                    checkRead(reporter, bmp, srcRect.fLeft, srcRect.fTop, startsWithPixels);
+                } else {
+                    // if we had no pixels beforehand and the readPixels failed then
+                    // our bitmap should still not have any pixels
+                    REPORTER_ASSERT(reporter, bmp.isNull());
+                }
+
+                // check the old webkit version of readPixels that clips the bitmap size
+                SkBitmap wkbmp;
+                success = canvas.readPixels(srcRect, &wkbmp);
+                SkIRect clippedRect = DEV_RECT;
+                if (clippedRect.intersect(srcRect)) {
+                    REPORTER_ASSERT(reporter, success);
+                    checkRead(reporter, wkbmp, clippedRect.fLeft, clippedRect.fTop, false);
+                } else {
+                    REPORTER_ASSERT(reporter, !success);
+                }
+            }
+        }
+    }
+}
+}
+
+#include "TestClassDef.h"
+DEFINE_GPUTESTCLASS("ReadPixels", ReadPixelsTestClass, ReadPixelsTest)
+