| /* | |
| * 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().detach()); | |
| 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<Surface*>(*message.fWindowSurface)){ | |
| windowSurface->release(nullptr); | |
| delete windowSurface; | |
| } | |
| return 0; | |
| } | |
| case kRenderPicture: { | |
| sk_sp<SkPicture> picture(message.fPicture); | |
| if(auto* windowSurface = reinterpret_cast<Surface*>(*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; | |
| } |