src/platform/qt/VideoProxy.cpp (view raw)
1/* Copyright (c) 2013-2018 Jeffrey Pfau
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6#include "VideoProxy.h"
7
8#include "CoreController.h"
9
10using namespace QGBA;
11
12VideoProxy::VideoProxy() {
13 mVideoLoggerRendererCreate(&m_logger.d, false);
14 m_logger.d.block = true;
15
16 m_logger.d.init = &cbind<&VideoProxy::init>;
17 m_logger.d.reset = &cbind<&VideoProxy::reset>;
18 m_logger.d.deinit = &cbind<&VideoProxy::deinit>;
19 m_logger.d.lock = &cbind<&VideoProxy::lock>;
20 m_logger.d.unlock = &cbind<&VideoProxy::unlock>;
21 m_logger.d.wait = &cbind<&VideoProxy::wait>;
22 m_logger.d.wake = &callback<void, int>::func<&VideoProxy::wake>;
23
24 m_logger.d.writeData = &callback<bool, const void*, size_t>::func<&VideoProxy::writeData>;
25 m_logger.d.readData = &callback<bool, void*, size_t, bool>::func<&VideoProxy::readData>;
26 m_logger.d.postEvent = &callback<void, enum mVideoLoggerEvent>::func<&VideoProxy::postEvent>;
27
28 connect(this, &VideoProxy::dataAvailable, this, &VideoProxy::processData);
29 connect(this, &VideoProxy::eventPosted, this, &VideoProxy::handleEvent);
30}
31
32void VideoProxy::attach(CoreController* controller) {
33 CoreController::Interrupter interrupter(controller);
34 controller->thread()->core->videoLogger = &m_logger.d;
35}
36
37void VideoProxy::processData() {
38 mVideoLoggerRendererRun(&m_logger.d, false);
39 m_fromThreadCond.wakeAll();
40}
41
42void VideoProxy::init() {
43 RingFIFOInit(&m_dirtyQueue, 0x80000);
44}
45
46void VideoProxy::reset() {
47 m_mutex.lock();
48 RingFIFOClear(&m_dirtyQueue);
49 m_toThreadCond.wakeAll();
50 m_mutex.unlock();
51}
52
53void VideoProxy::deinit() {
54 RingFIFODeinit(&m_dirtyQueue);
55}
56
57bool VideoProxy::writeData(const void* data, size_t length) {
58 while (!RingFIFOWrite(&m_dirtyQueue, data, length)) {
59 emit dataAvailable();
60 m_mutex.lock();
61 m_toThreadCond.wakeAll();
62 m_fromThreadCond.wait(&m_mutex);
63 m_mutex.unlock();
64 }
65 emit dataAvailable();
66 return true;
67}
68
69bool VideoProxy::readData(void* data, size_t length, bool block) {
70 bool read = false;
71 while (true) {
72 read = RingFIFORead(&m_dirtyQueue, data, length);
73 if (!block || read) {
74 break;
75 }
76 m_mutex.lock();
77 m_fromThreadCond.wakeAll();
78 m_toThreadCond.wait(&m_mutex);
79 m_mutex.unlock();
80 }
81 return read;
82}
83
84void VideoProxy::postEvent(enum mVideoLoggerEvent event) {
85 emit eventPosted(event);
86}
87
88void VideoProxy::handleEvent(int event) {
89 m_logger.d.handleEvent(&m_logger.d, static_cast<enum mVideoLoggerEvent>(event));
90}
91
92void VideoProxy::lock() {
93 m_mutex.lock();
94}
95
96void VideoProxy::unlock() {
97 m_mutex.unlock();
98}
99
100void VideoProxy::wait() {
101 m_mutex.lock();
102 while (RingFIFOSize(&m_dirtyQueue)) {
103 emit dataAvailable();
104 m_toThreadCond.wakeAll();
105 m_fromThreadCond.wait(&m_mutex, 1);
106 }
107 m_mutex.unlock();
108}
109
110void VideoProxy::wake(int y) {
111 if ((y & 15) == 15) {
112 m_toThreadCond.wakeAll();
113 }
114}