/* * Copyright 2021 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "modules/jetski/src/SurfaceThread.h" #include "tools/window/DisplayParams.h" #include "tools/window/WindowContext.h" #include "tools/window/android/WindowContextFactory_android.h" #include "include/core/SkCanvas.h" #include "include/core/SkPicture.h" #include "include/core/SkTypes.h" SurfaceThread::SurfaceThread() { pipe(fPipe); fRunning = true; pthread_create(&fThread, nullptr, pthread_main, this); } void SurfaceThread::postMessage(const Message& message) const { write(fPipe[1], &message, sizeof(message)); } void SurfaceThread::readMessage(Message* message) const { read(fPipe[0], message, sizeof(Message)); } void SurfaceThread::release() { pthread_join(fThread, nullptr); } int SurfaceThread::message_callback(int /* fd */, int /* events */, void* data) { auto surfaceThread = (SurfaceThread*)data; Message message; surfaceThread->readMessage(&message); // get target surface from Message switch (message.fType) { case kInitialize: { auto winctx = skwindow::MakeGLForAndroid(message.fNativeWindow, skwindow::DisplayParamsBuilder().build()); if (!winctx) { break; } *message.fWindowSurface = new WindowSurface(message.fNativeWindow, std::move(winctx)); break; } case kDestroy: { SkDebugf("surface destroyed, shutting down thread"); surfaceThread->fRunning = false; if(auto* windowSurface = reinterpret_cast(*message.fWindowSurface)){ windowSurface->release(nullptr); delete windowSurface; } return 0; } case kRenderPicture: { sk_sp picture(message.fPicture); if(auto* windowSurface = reinterpret_cast(*message.fWindowSurface)){ windowSurface->getCanvas()->drawPicture(picture); windowSurface->flushAndSubmit(); } break; } default: { // do nothing } } return 1; // continue receiving callbacks } void* SurfaceThread::pthread_main(void* arg) { auto surfaceThread = (SurfaceThread*)arg; // Looper setup ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS); ALooper_addFd(looper, surfaceThread->fPipe[0], 1, ALOOPER_EVENT_INPUT, surfaceThread->message_callback, surfaceThread); while (surfaceThread->fRunning) { int ident = ALOOPER_POLL_CALLBACK; while (ident == ALOOPER_POLL_CALLBACK) { ident = ALooper_pollOnce(0, nullptr, nullptr, nullptr); } if (ident >= 0) { SkDebugf("Unhandled ALooper_pollOnce ident=%d !", ident); } } return nullptr; }