flip Y in uploads to bottom-up textures (and add gm test)

Review URL: http://codereview.appspot.com/4756043/



git-svn-id: http://skia.googlecode.com/svn/trunk@1882 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gm/texdata.cpp b/gm/texdata.cpp
new file mode 100644
index 0000000..e1ad4b3
--- /dev/null
+++ b/gm/texdata.cpp
@@ -0,0 +1,139 @@
+#include "gm.h"
+#include "GrContext.h"
+#include "SkColorPriv.h"
+#include "SkDevice.h"
+
+namespace skiagm {
+
+extern GrContext* GetGr();
+
+static const int S = 200;
+
+class TexDataGM : public GM {
+public:
+    TexDataGM() {}
+
+protected:
+    virtual SkString onShortName() {
+        return SkString("texdata");
+    }
+
+    virtual SkISize onISize() {
+        return make_isize(2*S, 2*S);
+    }
+
+    void drawBG(SkCanvas* canvas) {
+        canvas->drawColor(0xff000000);
+    }
+
+    virtual void onDraw(SkCanvas* canvas) {
+        drawBG(canvas);
+        SkDevice* device = canvas->getDevice();
+        GrRenderTarget* target = (GrRenderTarget*) device->accessRenderTarget();
+        GrContext* ctx = GetGr();
+        if (ctx && target) {
+            SkPMColor gTextureData[(2 * S) * (2 * S)];
+            static const int stride = 2 * S;
+            static const SkPMColor gray  = SkPackARGB32(0x40, 0x40, 0x40, 0x40);
+            static const SkPMColor white = SkPackARGB32(0xff, 0xff, 0xff, 0xff);
+            static const SkPMColor red   = SkPackARGB32(0x80, 0x80, 0x00, 0x00);
+            static const SkPMColor blue  = SkPackARGB32(0x80, 0x00, 0x00, 0x80);
+            static const SkPMColor green = SkPackARGB32(0x80, 0x00, 0x80, 0x00);
+            static const SkPMColor black = SkPackARGB32(0x00, 0x00, 0x00, 0x00);
+            for (int i = 0; i < 2; ++i) {
+                int offset = 0;
+                // fill upper-left
+                for (int y = 0; y < S; ++y) {
+                    for (int x = 0; x < S; ++x) {
+                        gTextureData[offset + y * stride + x] = gray;
+                    }
+                }
+                // fill upper-right
+                offset = S;
+                for (int y = 0; y < S; ++y) {
+                    for (int x = 0; x < S; ++x) {
+                        gTextureData[offset + y * stride + x] = white;
+                    }
+                }
+                // fill lower left
+                offset = S * stride;
+                for (int y = 0; y < S; ++y) {
+                    for (int x = 0; x < S; ++x) {
+                        gTextureData[offset + y * stride + x] = black;
+                    }
+                }
+                // fill lower right
+                offset = S * stride + S;
+                for (int y = 0; y < S; ++y) {
+                    for (int x = 0; x < S; ++x) {
+                        gTextureData[offset + y * stride + x] = gray;
+                    }
+                }
+
+                GrTextureDesc desc;
+                desc.fAALevel   = kNone_GrAALevel;
+                // use RT flag bit because in GL it makes the texture be bottom-up
+                desc.fFlags     = i ? kRenderTarget_GrTextureFlagBit :
+                                      kNone_GrTextureFlags;
+                desc.fFormat    = kRGBA_8888_GrPixelConfig;
+                desc.fWidth     = 2 * S;
+                desc.fHeight    = 2 * S;
+                GrTexture* texture = 
+                    ctx->createUncachedTexture(desc, gTextureData, 0);
+
+                if (!texture) {
+                    return;
+                }
+                GrAutoUnref au(texture);
+
+                ctx->setClip(GrRect::MakeWH(2*S, 2*S));
+                ctx->setRenderTarget(target);
+
+                GrPaint paint;
+                paint.reset();
+                paint.fColor = 0xffffffff;
+                paint.fSrcBlendCoeff = kOne_BlendCoeff;
+                paint.fDstBlendCoeff = kISA_BlendCoeff;
+                GrMatrix vm;
+                if (i) {
+                    vm.setRotate(90, S , S);
+                } else {
+                    vm.reset();
+                }
+                ctx->setMatrix(vm);
+                GrMatrix tm;
+                tm = vm;
+                tm.postIDiv(2*S, 2*S);
+                paint.getTextureSampler(0)->setMatrix(tm);
+                paint.setTexture(0, texture);
+
+                ctx->drawRect(paint, GrRect::MakeWH(2*S, 2*S));
+
+                // now update the lower right of the texture in first pass
+                // or upper right in second pass
+                offset = 0;
+                for (int y = 0; y < S; ++y) {
+                    for (int x = 0; x < S; ++x) {
+                        gTextureData[offset + y * stride + x] = 
+                            ((x + y) % 2) ? (i ? green : red) : blue;
+                    }
+                }
+                // BUG: uploadTextureData doesn't force a flush
+                ctx->flush();
+                texture->uploadTextureData(S, i ? 0 : S, S, S, gTextureData, 4 * stride);
+                ctx->drawRect(paint, GrRect::MakeWH(2*S, 2*S));
+            }
+        }
+    }
+
+private:
+    typedef GM INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////
+
+static GM* MyFactory(void*) { return new TexDataGM; }
+static GMRegistry reg(MyFactory);
+
+}
+