blob: 7c4a3823cb553c1a8207050686bae0b82f915f40 [file] [log] [blame]
/*
* 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/androidkit/src/SurfaceThread.h"
#include "tools/sk_app/WindowContext.h"
#include "tools/sk_app/android/WindowContextFactory_android.h"
#include "include/core/SkCanvas.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: {
sk_app::DisplayParams params;
auto winctx = sk_app::window_context_factory::MakeGLForAndroid(message.fNativeWindow, params);
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;
break;
}
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) {
const int ident = ALooper_pollAll(0, nullptr, nullptr, nullptr);
if (ident >= 0) {
SkDebugf("Unhandled ALooper_pollAll ident=%d !", ident);
}
}
return nullptr;
}