1 #include <jni.h> 2 #include <sys/time.h> 3 #include <time.h> 4 #include <android/log.h> 5 #include <stdint.h> 6 7 #include "GrContext.h" 8 #include "SkGpuCanvas.h" 9 #include "SkPaint.h" 10 #include "SkString.h" 11 #include "SkTime.h" 12 13 #include "GrGLConfig.h" 14 15 static GrContext* make_context() { 16 SkDebugf("---- before create\n"); 17 GrContext* ctx = GrContext::Create(GrGpu::kOpenGL_Shaders_Engine, 0); 18 // GrContext* ctx = GrContext::Create(GrGpu::kOpenGL_Fixed_Engine, 0); 19 SkDebugf("---- after create %p\n", ctx); 20 return ctx; 21 } 22 23 /////////////////////////////////////////////////////////////////////////////// 24 25 void gr_run_unittests() {} 26 27 #include "FlingState.h" 28 #include "GrTouchGesture.h" 29 #include "SkView.h" 30 31 typedef SkView* (*SkViewFactory)(); 32 33 // these values must match those in Ganesh.java 34 enum TouchState { 35 kUnknown_TouchState, 36 kDown_TouchState, 37 kMoved_TouchState, 38 kUp_TouchState 39 }; 40 41 struct State { 42 State(); 43 ~State(); 44 45 int countSlides() const { return fFactory.count(); } 46 const char* getSlideTitle(int index) const; 47 void chooseSlide(int index) { 48 SkDebugf("----- index %d\n", index); 49 if (index < fFactory.count()) { 50 this->setView(fFactory[index]()); 51 } 52 } 53 54 void setViewport(int w, int h); 55 int getWidth() const { return fViewport.fX; } 56 int getHeight() const { return fViewport.fY; } 57 58 void handleTouch(void*, TouchState, float x, float y); 59 void applyMatrix(SkCanvas*); 60 61 SkView* getView() const { return fView; } 62 63 private: 64 SkView* fView; 65 SkIPoint fViewport; 66 67 GrTouchGesture fGesture; 68 69 SkTDArray<SkViewFactory> fFactory; 70 71 void setView(SkView* view) { 72 SkSafeUnref(fView); 73 fView = view; 74 75 view->setVisibleP(true); 76 view->setClipToBounds(false); 77 view->setSize(SkIntToScalar(fViewport.fX), 78 SkIntToScalar(fViewport.fY)); 79 } 80 }; 81 82 /////////////////////////////////////////////////////////////////////////////// 83 84 #include "SampleCode.h" 85 86 SkViewRegister* SkViewRegister::gHead; 87 SkViewRegister::SkViewRegister(SkViewFactory fact) : fFact(fact) { 88 static bool gOnce; 89 if (!gOnce) { 90 gHead = NULL; 91 gOnce = true; 92 } 93 94 fChain = gHead; 95 gHead = this; 96 } 97 98 static const char gCharEvtName[] = "SampleCode_Char_Event"; 99 static const char gKeyEvtName[] = "SampleCode_Key_Event"; 100 static const char gTitleEvtName[] = "SampleCode_Title_Event"; 101 static const char gPrefSizeEvtName[] = "SampleCode_PrefSize_Event"; 102 static const char gFastTextEvtName[] = "SampleCode_FastText_Event"; 103 104 bool SampleCode::CharQ(const SkEvent& evt, SkUnichar* outUni) { 105 if (evt.isType(gCharEvtName, sizeof(gCharEvtName) - 1)) { 106 if (outUni) { 107 *outUni = evt.getFast32(); 108 } 109 return true; 110 } 111 return false; 112 } 113 114 bool SampleCode::KeyQ(const SkEvent& evt, SkKey* outKey) { 115 if (evt.isType(gKeyEvtName, sizeof(gKeyEvtName) - 1)) { 116 if (outKey) { 117 *outKey = (SkKey)evt.getFast32(); 118 } 119 return true; 120 } 121 return false; 122 } 123 124 bool SampleCode::TitleQ(const SkEvent& evt) { 125 return evt.isType(gTitleEvtName, sizeof(gTitleEvtName) - 1); 126 } 127 128 void SampleCode::TitleR(SkEvent* evt, const char title[]) { 129 GrAssert(evt && TitleQ(*evt)); 130 evt->setString(gTitleEvtName, title); 131 } 132 133 bool SampleCode::PrefSizeQ(const SkEvent& evt) { 134 return evt.isType(gPrefSizeEvtName, sizeof(gPrefSizeEvtName) - 1); 135 } 136 137 void SampleCode::PrefSizeR(SkEvent* evt, SkScalar width, SkScalar height) { 138 GrAssert(evt && PrefSizeQ(*evt)); 139 SkScalar size[2]; 140 size[0] = width; 141 size[1] = height; 142 evt->setScalars(gPrefSizeEvtName, 2, size); 143 } 144 145 bool SampleCode::FastTextQ(const SkEvent& evt) { 146 return evt.isType(gFastTextEvtName, sizeof(gFastTextEvtName) - 1); 147 } 148 149 static SkMSec gAnimTime; 150 static SkMSec gAnimTimePrev; 151 152 SkMSec SampleCode::GetAnimTime() { return gAnimTime; } 153 SkMSec SampleCode::GetAnimTimeDelta() { return gAnimTime - gAnimTimePrev; } 154 SkScalar SampleCode::GetAnimSecondsDelta() { 155 return SkDoubleToScalar(GetAnimTimeDelta() / 1000.0); 156 } 157 158 SkScalar SampleCode::GetAnimScalar(SkScalar speed, SkScalar period) { 159 // since gAnimTime can be up to 32 bits, we can't convert it to a float 160 // or we'll lose the low bits. Hence we use doubles for the intermediate 161 // calculations 162 double seconds = (double)gAnimTime / 1000.0; 163 double value = SkScalarToDouble(speed) * seconds; 164 if (period) { 165 value = ::fmod(value, SkScalarToDouble(period)); 166 } 167 return SkDoubleToScalar(value); 168 } 169 170 static void drawIntoCanvas(State* state, SkCanvas* canvas) { 171 gAnimTime = SkTime::GetMSecs(); 172 SkView* view = state->getView(); 173 view->draw(canvas); 174 } 175 176 /////////////////////////////////////////////////////////////////////////////// 177 178 static void resetGpuState(); 179 180 State::State() { 181 fViewport.set(0, 0); 182 183 const SkViewRegister* reg = SkViewRegister::Head(); 184 while (reg) { 185 *fFactory.append() = reg->factory(); 186 reg = reg->next(); 187 } 188 189 SkDebugf("----- %d slides\n", fFactory.count()); 190 fView = NULL; 191 this->chooseSlide(0); 192 } 193 194 State::~State() { 195 SkSafeUnref(fView); 196 } 197 198 void State::setViewport(int w, int h) { 199 fViewport.set(w, h); 200 if (fView) { 201 fView->setSize(SkIntToScalar(w), SkIntToScalar(h)); 202 } 203 resetGpuState(); 204 } 205 206 const char* State::getSlideTitle(int index) const { 207 SkEvent evt(gTitleEvtName); 208 evt.setFast32(index); 209 { 210 SkView* view = fFactory[index](); 211 view->doQuery(&evt); 212 view->unref(); 213 } 214 return evt.findString(gTitleEvtName); 215 } 216 217 void State::handleTouch(void* owner, TouchState state, float x, float y) { 218 switch (state) { 219 case kDown_TouchState: 220 fGesture.touchBegin(owner, x, y); 221 break; 222 case kMoved_TouchState: 223 fGesture.touchMoved(owner, x, y); 224 break; 225 case kUp_TouchState: 226 fGesture.touchEnd(owner); 227 break; 228 } 229 } 230 231 void State::applyMatrix(SkCanvas* canvas) { 232 const SkMatrix& localM = fGesture.localM(); 233 if (localM.getType() & SkMatrix::kScale_Mask) { 234 canvas->setExternalMatrix(&localM); 235 } 236 canvas->concat(localM); 237 canvas->concat(fGesture.globalM()); 238 } 239 240 static State* get_state() { 241 static State* gState; 242 if (NULL == gState) { 243 gState = new State; 244 } 245 return gState; 246 } 247 248 /////////////////////////////////////////////////////////////////////////////// 249 250 static GrContext* gContext; 251 static int gWidth; 252 static int gHeight; 253 static float gX, gY; 254 255 static void resetGpuState() { 256 if (NULL == gContext) { 257 SkDebugf("creating context for first time\n"); 258 gContext = make_context(); 259 } else { 260 SkDebugf("------ gContext refcnt=%d\n", gContext->refcnt()); 261 gContext->abandonAllTextures(); 262 gContext->unref(); 263 gContext = make_context(); 264 } 265 } 266 267 static void doDraw() { 268 if (NULL == gContext) { 269 gContext = make_context(); 270 } 271 272 State* state = get_state(); 273 SkBitmap viewport; 274 viewport.setConfig(SkBitmap::kARGB_8888_Config, 275 state->getWidth(), state->getHeight()); 276 277 SkGpuCanvas canvas(gContext); 278 279 canvas.setBitmapDevice(viewport); 280 state->applyMatrix(&canvas); 281 282 drawIntoCanvas(state, &canvas); 283 284 GrGLCheckErr(); 285 GrGLClearErr(); 286 // gContext->checkError(); 287 // gContext->clearError(); 288 289 if (true) { 290 static const int FRAME_COUNT = 32; 291 static SkMSec gDuration; 292 293 static SkMSec gNow; 294 static int gFrameCounter; 295 if (++gFrameCounter == FRAME_COUNT) { 296 gFrameCounter = 0; 297 SkMSec now = SkTime::GetMSecs(); 298 299 gDuration = now - gNow; 300 gNow = now; 301 } 302 303 int fps = (FRAME_COUNT * 1000) / gDuration; 304 SkString str; 305 str.printf("FPS=%3d MS=%3d", fps, gDuration / FRAME_COUNT); 306 307 SkGpuCanvas c(gContext); 308 c.setBitmapDevice(viewport); 309 310 SkPaint p; 311 p.setAntiAlias(true); 312 SkRect r = { 0, 0, 110, 16 }; 313 p.setColor(SK_ColorWHITE); 314 c.drawRect(r, p); 315 p.setColor(SK_ColorBLACK); 316 c.drawText(str.c_str(), str.size(), 4, 12, p); 317 } 318 } 319 320 /////////////////////////////////////////////////////////////////////////////// 321 322 extern "C" { 323 JNIEXPORT void JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeSurfaceCreated( 324 JNIEnv*, jobject); 325 JNIEXPORT void JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeViewport(JNIEnv*, jobject, 326 jint w, jint h); 327 JNIEXPORT void JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeDrawFrame(JNIEnv*, jobject); 328 JNIEXPORT void JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeTouch(JNIEnv*, jobject, 329 jint id, jint type, jfloat x, jfloat y); 330 331 JNIEXPORT int JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeCountSlides(JNIEnv*, jobject); 332 JNIEXPORT jobject JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeGetSlideTitle(JNIEnv*, jobject, jint index); 333 JNIEXPORT void JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeChooseSlide(JNIEnv*, jobject, jint index); 334 } 335 336 JNIEXPORT void JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeSurfaceCreated( 337 JNIEnv*, jobject) { 338 SkDebugf("------ nativeSurfaceCreated\n"); 339 resetGpuState(); 340 SkDebugf("------ end nativeSurfaceCreated\n"); 341 } 342 343 JNIEXPORT void JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeViewport(JNIEnv*, jobject, 344 jint w, jint h) { 345 State* state = get_state(); 346 SkDebugf("---- state.setviewport %p %d %d\n", state, w, h); 347 state->setViewport(w, h); 348 SkDebugf("---- end setviewport\n"); 349 } 350 351 JNIEXPORT void JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeDrawFrame(JNIEnv*, jobject) { 352 doDraw(); 353 } 354 355 union IntPtr { 356 jint fInt; 357 void* fPtr; 358 }; 359 static void* int2ptr(jint n) { 360 IntPtr data; 361 data.fInt = n; 362 return data.fPtr; 363 } 364 365 JNIEXPORT void JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeTouch(JNIEnv*, jobject, 366 jint id, jint type, jfloat x, jfloat y) { 367 get_state()->handleTouch(int2ptr(id), (TouchState)type, x, y); 368 } 369 370 //////////// 371 372 JNIEXPORT int JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeCountSlides(JNIEnv*, jobject) { 373 return get_state()->countSlides(); 374 } 375 376 JNIEXPORT jobject JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeGetSlideTitle(JNIEnv* env, jobject, jint index) { 377 return env->NewStringUTF(get_state()->getSlideTitle(index)); 378 } 379 380 JNIEXPORT void JNICALL Java_com_tetrark_ganesh_MyRenderer_nativeChooseSlide(JNIEnv*, jobject, jint index) { 381 get_state()->chooseSlide(index); 382 } 383 384 385 386 387 388