You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
146 lines
3.7 KiB
146 lines
3.7 KiB
3 years ago
|
/*
|
||
|
Copyright 2020-2021 Brad Parker
|
||
|
|
||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
you may not use this file except in compliance with the License.
|
||
|
You may obtain a copy of the License at
|
||
|
|
||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||
|
|
||
|
Unless required by applicable law or agreed to in writing, software
|
||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
See the License for the specific language governing permissions and
|
||
|
limitations under the License.
|
||
|
*/
|
||
|
|
||
|
#include <QOpenGLContext>
|
||
|
#include <QOpenGLFramebufferObject>
|
||
|
#include <iostream>
|
||
|
#include "core.h"
|
||
|
#include "../common/video.h"
|
||
|
|
||
|
void Core::videoRefresh(const void *data, unsigned width, unsigned height, size_t pitch) {
|
||
|
if(!data || m_isHWRender) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if(width != m_width || height != m_height || pitch != m_pitch) {
|
||
|
std::cout << "new video size: " << width << "x" << height << " (pitch " << pitch << ")" << std::endl;
|
||
|
|
||
|
if(m_imgData) {
|
||
|
delete []m_imgData;
|
||
|
}
|
||
|
|
||
|
m_width = width;
|
||
|
m_height = height;
|
||
|
m_pitch = pitch;
|
||
|
|
||
|
m_imgData = new unsigned char[pitch * height];
|
||
|
}
|
||
|
|
||
|
memcpy(m_imgData, data, pitch * height);
|
||
|
|
||
|
if(m_pixFmt == RETRO_PIXEL_FORMAT_0RGB1555) {
|
||
|
m_img = QImage(m_imgData, width, height, pitch, QImage::Format_RGB555);
|
||
|
}else if(m_pixFmt == RETRO_PIXEL_FORMAT_XRGB8888) {
|
||
|
m_img = QImage(m_imgData, width, height, pitch, QImage::Format_RGB32);
|
||
|
}else if(m_pixFmt == RETRO_PIXEL_FORMAT_RGB565) {
|
||
|
m_img = QImage(m_imgData, width, height, pitch, QImage::Format_RGB16);
|
||
|
}
|
||
|
|
||
|
m_img = m_img.mirrored(true, false);
|
||
|
m_img = m_img.mirrored(true, false);
|
||
|
}
|
||
|
|
||
|
float Core::getVideoRate() {
|
||
|
return VideoState::instance()->avInfo()->timing.fps;
|
||
|
}
|
||
|
|
||
|
void Core::render() {
|
||
|
if(m_timer.isActive())
|
||
|
return;
|
||
|
|
||
|
emit repaint();
|
||
|
|
||
|
emit doneRendering();
|
||
|
}
|
||
|
|
||
|
void Core::onGotFrameSwap() {
|
||
|
if(m_timer.isActive())
|
||
|
return;
|
||
|
|
||
|
if(m_doRender) {
|
||
|
m_elapsedTimer.start();
|
||
|
|
||
|
QOpenGLContext *ctx = VideoState::instance()->context();
|
||
|
QOpenGLFramebufferObject *fbo = VideoState::instance()->fbo();
|
||
|
|
||
|
if(ctx) {
|
||
|
ctx->makeCurrent(ctx->surface());
|
||
|
|
||
|
if(m_isHWRender && fbo) {
|
||
|
fbo->bind();
|
||
|
}
|
||
|
|
||
|
m_retroRun();
|
||
|
|
||
|
if(m_isHWRender && fbo) {
|
||
|
fbo->release();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
m_timer.disconnect();
|
||
|
|
||
|
connect(&m_timer, &QTimer::timeout, this, &Core::render);
|
||
|
|
||
|
m_timer.start(0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
uintptr_t Core::getCurrentFramebuffer() {
|
||
|
QOpenGLContext *ctx = VideoState::instance()->context();
|
||
|
|
||
|
if(ctx) {
|
||
|
QOpenGLFramebufferObject *fbo = VideoState::instance()->fbo();
|
||
|
|
||
|
if(fbo) {
|
||
|
return fbo->handle();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void* Core::getProcAddress(const char *sym) {
|
||
|
QOpenGLContext *ctx = VideoState::instance()->context();
|
||
|
|
||
|
if(ctx)
|
||
|
return reinterpret_cast<void*>(ctx->getProcAddress(sym));
|
||
|
|
||
|
return nullptr;
|
||
|
}
|
||
|
|
||
|
bool Core::isHWRender() {
|
||
|
return m_isHWRender;
|
||
|
}
|
||
|
|
||
|
void Core::blitFBO() {
|
||
|
// hardware-accelerated cores draw into their own frame buffer object, we must push that to the screen now
|
||
|
auto videoState = VideoState::instance();
|
||
|
QOpenGLContext *ctx = videoState->context();
|
||
|
QOpenGLFramebufferObject *fbo = videoState->fbo();
|
||
|
struct retro_system_av_info *avInfo = videoState->avInfo();
|
||
|
|
||
|
if(ctx && fbo && fbo->isValid() && fbo->hasOpenGLFramebufferBlit()) {
|
||
|
fbo->bind();
|
||
|
// Copy the rendered frame buffer data from the core directly onto the screen.
|
||
|
QOpenGLFramebufferObject::blitFramebuffer(0, videoState->aspectCorrectedRect(), fbo, QRect(0, 0, avInfo->geometry.base_width, avInfo->geometry.base_height), GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||
|
fbo->release();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
QImage* Core::getImage() {
|
||
|
return &m_img;
|
||
|
}
|