1/* 2 * Copyright 2021 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7#include "modules/androidkit/src/SurfaceThread.h" 8 9#include "tools/sk_app/WindowContext.h" 10#include "tools/sk_app/android/WindowContextFactory_android.h" 11 12#include "include/core/SkCanvas.h" 13#include "include/core/SkTypes.h" 14 15SurfaceThread::SurfaceThread() { 16 pipe(fPipe); 17 fRunning = true; 18 pthread_create(&fThread, nullptr, pthread_main, this); 19} 20 21void SurfaceThread::postMessage(const Message& message) const { 22 write(fPipe[1], &message, sizeof(message)); 23} 24 25void SurfaceThread::readMessage(Message* message) const { 26 read(fPipe[0], message, sizeof(Message)); 27} 28 29void SurfaceThread::release() { 30 pthread_join(fThread, nullptr); 31} 32 33int SurfaceThread::message_callback(int /* fd */, int /* events */, void* data) { 34 auto surfaceThread = (SurfaceThread*)data; 35 Message message; 36 surfaceThread->readMessage(&message); 37 // get target surface from Message 38 39 switch (message.fType) { 40 case kInitialize: { 41 sk_app::DisplayParams params; 42 auto winctx = sk_app::window_context_factory::MakeGLForAndroid(message.fNativeWindow, params); 43 if (!winctx) { 44 break; 45 } 46 *message.fWindowSurface = new WindowSurface(message.fNativeWindow, std::move(winctx)); 47 break; 48 } 49 case kDestroy: { 50 SkDebugf("surface destroyed, shutting down thread"); 51 surfaceThread->fRunning = false; 52 if(auto* windowSurface = reinterpret_cast<Surface*>(*message.fWindowSurface)){ 53 windowSurface->release(nullptr); 54 delete windowSurface; 55 } 56 return 0; 57 break; 58 } 59 case kRenderPicture: { 60 sk_sp<SkPicture> picture(message.fPicture); 61 if(auto* windowSurface = reinterpret_cast<Surface*>(*message.fWindowSurface)){ 62 windowSurface->getCanvas()->drawPicture(picture); 63 windowSurface->flushAndSubmit(); 64 } 65 break; 66 } 67 default: { 68 // do nothing 69 } 70 } 71 72 return 1; // continue receiving callbacks 73} 74 75void* SurfaceThread::pthread_main(void* arg) { 76 auto surfaceThread = (SurfaceThread*)arg; 77 // Looper setup 78 ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); 79 ALooper_addFd(looper, surfaceThread->fPipe[0], 1, ALOOPER_EVENT_INPUT, 80 surfaceThread->message_callback, surfaceThread); 81 82 while (surfaceThread->fRunning) { 83 const int ident = ALooper_pollAll(0, nullptr, nullptr, nullptr); 84 85 if (ident >= 0) { 86 SkDebugf("Unhandled ALooper_pollAll ident=%d !", ident); 87 } 88 } 89 return nullptr; 90} 91