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
SurfaceThread()15 SurfaceThread::SurfaceThread() {
16 pipe(fPipe);
17 fRunning = true;
18 pthread_create(&fThread, nullptr, pthread_main, this);
19 }
20
postMessage(const Message & message) const21 void SurfaceThread::postMessage(const Message& message) const {
22 write(fPipe[1], &message, sizeof(message));
23 }
24
readMessage(Message * message) const25 void SurfaceThread::readMessage(Message* message) const {
26 read(fPipe[0], message, sizeof(Message));
27 }
28
release()29 void SurfaceThread::release() {
30 pthread_join(fThread, nullptr);
31 }
32
message_callback(int,int,void * data)33 int 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
pthread_main(void * arg)75 void* 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