add gpu backend (not hooked up yet)



git-svn-id: http://skia.googlecode.com/svn/trunk@649 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/src/app-android.cpp b/gpu/src/app-android.cpp
new file mode 100644
index 0000000..eea9a4d
--- /dev/null
+++ b/gpu/src/app-android.cpp
@@ -0,0 +1,387 @@
+#include <jni.h>
+#include <sys/time.h>
+#include <time.h>
+#include <android/log.h>
+#include <stdint.h>
+
+#include "GrContext.h"
+#include "SkGpuCanvas.h"
+#include "SkPaint.h"
+#include "SkString.h"
+#include "SkTime.h"
+
+#include "GrGLConfig.h"
+
+static GrContext* make_context() {
+    SkDebugf("---- before create\n");
+    GrContext* ctx = GrContext::Create(GrGpu::kOpenGL_Shaders_Engine, NULL);
+//    GrContext* ctx = GrContext::Create(GrGpu::kOpenGL_Fixed_Engine, NULL);
+    SkDebugf("---- after create %p\n", ctx);
+    return ctx;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void gr_run_unittests() {}
+
+#include "FlingState.h"
+#include "GrTouchGesture.h"
+#include "SkView.h"
+
+typedef SkView* (*SkViewFactory)();
+
+// these values must match those in Ganesh.java
+enum TouchState {
+    kUnknown_TouchState,
+    kDown_TouchState,
+    kMoved_TouchState,
+    kUp_TouchState
+};
+
+struct State {
+    State();
+    ~State();
+
+    int countSlides() const { return fFactory.count(); }
+    const char* getSlideTitle(int index) const;
+    void chooseSlide(int index) {
+        SkDebugf("----- index %d\n", index);
+        if (index < fFactory.count()) {
+            this->setView(fFactory[index]());
+        }
+    }
+
+    void setViewport(int w, int h);
+    int getWidth() const { return fViewport.fX; }
+    int getHeight() const { return fViewport.fY; }
+    
+    void handleTouch(void*, TouchState, float x, float y);
+    void applyMatrix(SkCanvas*);
+
+    SkView* getView() const { return fView; }
+
+private:
+    SkView*     fView;
+    SkIPoint    fViewport;
+    
+    GrTouchGesture fGesture;
+
+    SkTDArray<SkViewFactory> fFactory;
+
+    void setView(SkView* view) {
+        SkSafeUnref(fView);
+        fView = view;
+
+        view->setVisibleP(true);
+        view->setClipToBounds(false);
+        view->setSize(SkIntToScalar(fViewport.fX),
+                      SkIntToScalar(fViewport.fY));
+    }
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+#include "SampleCode.h"
+
+SkViewRegister* SkViewRegister::gHead;
+SkViewRegister::SkViewRegister(SkViewFactory fact) : fFact(fact) {
+    static bool gOnce;
+    if (!gOnce) {
+        gHead = NULL;
+        gOnce = true;
+    }
+    
+    fChain = gHead;
+    gHead = this;
+}
+
+static const char gCharEvtName[] = "SampleCode_Char_Event";
+static const char gKeyEvtName[] = "SampleCode_Key_Event";
+static const char gTitleEvtName[] = "SampleCode_Title_Event";
+static const char gPrefSizeEvtName[] = "SampleCode_PrefSize_Event";
+static const char gFastTextEvtName[] = "SampleCode_FastText_Event";
+
+bool SampleCode::CharQ(const SkEvent& evt, SkUnichar* outUni) {
+    if (evt.isType(gCharEvtName, sizeof(gCharEvtName) - 1)) {
+        if (outUni) {
+            *outUni = evt.getFast32();
+        }
+        return true;
+    }
+    return false;
+}
+
+bool SampleCode::KeyQ(const SkEvent& evt, SkKey* outKey) {
+    if (evt.isType(gKeyEvtName, sizeof(gKeyEvtName) - 1)) {
+        if (outKey) {
+            *outKey = (SkKey)evt.getFast32();
+        }
+        return true;
+    }
+    return false;
+}
+
+bool SampleCode::TitleQ(const SkEvent& evt) {
+    return evt.isType(gTitleEvtName, sizeof(gTitleEvtName) - 1);
+}
+
+void SampleCode::TitleR(SkEvent* evt, const char title[]) {
+    GrAssert(evt && TitleQ(*evt));
+    evt->setString(gTitleEvtName, title);
+}
+
+bool SampleCode::PrefSizeQ(const SkEvent& evt) {
+    return evt.isType(gPrefSizeEvtName, sizeof(gPrefSizeEvtName) - 1);
+}
+
+void SampleCode::PrefSizeR(SkEvent* evt, SkScalar width, SkScalar height) {
+    GrAssert(evt && PrefSizeQ(*evt));
+    SkScalar size[2];
+    size[0] = width;
+    size[1] = height;
+    evt->setScalars(gPrefSizeEvtName, 2, size);
+}
+
+bool SampleCode::FastTextQ(const SkEvent& evt) {
+    return evt.isType(gFastTextEvtName, sizeof(gFastTextEvtName) - 1);
+}
+
+static SkMSec gAnimTime;
+static SkMSec gAnimTimePrev;
+
+SkMSec SampleCode::GetAnimTime() { return gAnimTime; }
+SkMSec SampleCode::GetAnimTimeDelta() { return gAnimTime - gAnimTimePrev; }
+SkScalar SampleCode::GetAnimSecondsDelta() {
+    return SkDoubleToScalar(GetAnimTimeDelta() / 1000.0);
+}
+
+SkScalar SampleCode::GetAnimScalar(SkScalar speed, SkScalar period) {
+    // since gAnimTime can be up to 32 bits, we can't convert it to a float
+    // or we'll lose the low bits. Hence we use doubles for the intermediate
+    // calculations
+    double seconds = (double)gAnimTime / 1000.0;
+    double value = SkScalarToDouble(speed) * seconds;
+    if (period) {
+        value = ::fmod(value, SkScalarToDouble(period));
+    }
+    return SkDoubleToScalar(value);
+}
+
+static void drawIntoCanvas(State* state, SkCanvas* canvas) {
+    gAnimTime = SkTime::GetMSecs();
+    SkView* view = state->getView();
+    view->draw(canvas);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static void resetGpuState();
+
+State::State() {
+    fViewport.set(0, 0);
+
+    const SkViewRegister* reg = SkViewRegister::Head();
+    while (reg) {
+        *fFactory.append() = reg->factory();
+        reg = reg->next();
+    }
+
+    SkDebugf("----- %d slides\n", fFactory.count());
+    fView = NULL;
+    this->chooseSlide(0);
+}
+
+State::~State() {
+    SkSafeUnref(fView);
+}
+
+void State::setViewport(int w, int h) {
+    fViewport.set(w, h);
+    if (fView) {
+        fView->setSize(SkIntToScalar(w), SkIntToScalar(h));
+    }
+    resetGpuState();
+}
+
+const char* State::getSlideTitle(int index) const {
+    SkEvent evt(gTitleEvtName);
+    evt.setFast32(index);
+    {
+        SkView* view = fFactory[index]();
+        view->doQuery(&evt);
+        view->unref();
+    }
+    return evt.findString(gTitleEvtName);
+}
+
+void State::handleTouch(void* owner, TouchState state, float x, float y) {
+    switch (state) {
+        case kDown_TouchState:
+            fGesture.touchBegin(owner, x, y);
+            break;
+        case kMoved_TouchState:
+            fGesture.touchMoved(owner, x, y);
+            break;
+        case kUp_TouchState:
+            fGesture.touchEnd(owner);
+            break;
+    }
+}
+
+void State::applyMatrix(SkCanvas* canvas) {
+    const SkMatrix& localM = fGesture.localM();
+    if (localM.getType() & SkMatrix::kScale_Mask) {
+        canvas->setExternalMatrix(&localM);
+    }
+    canvas->concat(localM);
+    canvas->concat(fGesture.globalM());
+}
+
+static State* get_state() {
+    static State* gState;
+    if (NULL == gState) {
+        gState = new State;
+    }
+    return gState;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static GrContext* gContext;
+static int gWidth;
+static int gHeight;
+static float gX, gY;
+
+static void resetGpuState() {
+    if (NULL == gContext) {
+        SkDebugf("creating context for first time\n");
+        gContext = make_context();
+    } else {
+        SkDebugf("------ gContext refcnt=%d\n", gContext->refcnt());
+        gContext->abandonAllTextures();
+        gContext->unref();
+        gContext = make_context();
+    }
+}
+
+static void doDraw() {
+    if (NULL == gContext) {
+        gContext = make_context();
+    }
+
+    State* state = get_state();
+    SkBitmap viewport;
+    viewport.setConfig(SkBitmap::kARGB_8888_Config,
+                       state->getWidth(), state->getHeight());
+
+    SkGpuCanvas canvas(gContext);
+
+    canvas.setBitmapDevice(viewport);
+    state->applyMatrix(&canvas);
+
+    drawIntoCanvas(state, &canvas);
+
+    GrGLCheckErr();
+    GrGLClearErr();
+//    gContext->checkError();
+//    gContext->clearError();
+
+    if (true) {
+        static const int FRAME_COUNT = 32;
+        static SkMSec gDuration;
+
+        static SkMSec gNow;
+        static int gFrameCounter;
+        if (++gFrameCounter == FRAME_COUNT) {
+            gFrameCounter = 0;
+            SkMSec now = SkTime::GetMSecs();
+
+            gDuration = now - gNow;
+            gNow = now;
+        }
+
+        int fps = (FRAME_COUNT * 1000) / gDuration;
+        SkString str;
+        str.printf("FPS=%3d MS=%3d", fps, gDuration / FRAME_COUNT);
+        
+        SkGpuCanvas c(gContext);
+        c.setBitmapDevice(viewport);
+
+        SkPaint p;
+        p.setAntiAlias(true);
+        SkRect r = { 0, 0, 110, 16 };
+        p.setColor(SK_ColorWHITE);
+        c.drawRect(r, p);
+        p.setColor(SK_ColorBLACK);
+        c.drawText(str.c_str(), str.size(), 4, 12, p);
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+extern "C" {
+    JNIEXPORT void JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeSurfaceCreated(
+                                                           JNIEnv*, jobject);
+    JNIEXPORT void JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeViewport(JNIEnv*, jobject,
+                                                                             jint w, jint h);
+    JNIEXPORT void JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeDrawFrame(JNIEnv*, jobject);
+    JNIEXPORT void JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeTouch(JNIEnv*, jobject,
+                                        jint id, jint type, jfloat x, jfloat y);
+
+    JNIEXPORT int JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeCountSlides(JNIEnv*, jobject);
+    JNIEXPORT jobject JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeGetSlideTitle(JNIEnv*, jobject, jint index);
+    JNIEXPORT void JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeChooseSlide(JNIEnv*, jobject, jint index);
+}
+
+JNIEXPORT void JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeSurfaceCreated(
+                                                            JNIEnv*, jobject) {
+    SkDebugf("------ nativeSurfaceCreated\n");
+    resetGpuState();
+    SkDebugf("------ end nativeSurfaceCreated\n");
+}
+
+JNIEXPORT void JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeViewport(JNIEnv*, jobject,
+                                                       jint w, jint h) {
+    State* state = get_state();
+    SkDebugf("---- state.setviewport %p %d %d\n", state, w, h);
+    state->setViewport(w, h);
+    SkDebugf("---- end setviewport\n");
+}
+
+JNIEXPORT void JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeDrawFrame(JNIEnv*, jobject) {
+    doDraw();
+}
+
+union IntPtr {
+    jint    fInt;
+    void*   fPtr;
+};
+static void* int2ptr(jint n) {
+    IntPtr data;
+    data.fInt = n;
+    return data.fPtr;
+}
+
+JNIEXPORT void JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeTouch(JNIEnv*, jobject,
+                                      jint id, jint type, jfloat x, jfloat y) {
+    get_state()->handleTouch(int2ptr(id), (TouchState)type, x, y);
+}
+
+////////////
+
+JNIEXPORT int JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeCountSlides(JNIEnv*, jobject) {
+    return get_state()->countSlides();
+}
+
+JNIEXPORT jobject JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeGetSlideTitle(JNIEnv* env, jobject, jint index) {
+    return env->NewStringUTF(get_state()->getSlideTitle(index));
+}
+
+JNIEXPORT void JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeChooseSlide(JNIEnv*, jobject, jint index) {
+    get_state()->chooseSlide(index);
+}
+
+
+
+
+