all repos — mgba @ eeee6fe44eb11e77774c7bb3f08c2016682d33cd

mGBA Game Boy Advance Emulator

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}