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