From a5564fa6dd38ace91cdd10a39bee0d4059648623 Mon Sep 17 00:00:00 2001 From: Pino Toscano Date: Thu, 22 Oct 2009 20:54:11 +0000 Subject: [PATCH] use a queue for the rendering requests of the rendering thread this should avoid multiple generator instance to step on each other toes, making spectre crashing svn path=/trunk/KDE/kdegraphics/okular/; revision=1039159 --- generators/spectre/generator_ghostview.cpp | 21 ++-- generators/spectre/rendererthread.cpp | 108 ++++++++++----------- generators/spectre/rendererthread.h | 38 ++++++-- 3 files changed, 94 insertions(+), 73 deletions(-) diff --git a/generators/spectre/generator_ghostview.cpp b/generators/spectre/generator_ghostview.cpp index ea0596353..9439fe9a8 100644 --- a/generators/spectre/generator_ghostview.cpp +++ b/generators/spectre/generator_ghostview.cpp @@ -229,27 +229,32 @@ void GSGenerator::generatePixmap( Okular::PixmapRequest * req ) SpectrePage *page = spectre_document_get_page(m_internalDocument, req->pageNumber()); GSRendererThread *renderer = GSRendererThread::getCreateRenderer(); - renderer->setPlatformFonts(GSSettings::platformFonts()); + + GSRendererThreadRequest gsreq(this); + gsreq.spectrePage = page; + gsreq.platformFonts = GSSettings::platformFonts(); int graphicsAA = 1; int textAA = 1; if (cache_AAgfx) graphicsAA = 4; if (cache_AAtext) textAA = 2; - renderer->setAABits(graphicsAA, textAA); + gsreq.textAAbits = textAA; + gsreq.graphicsAAbits = graphicsAA; - renderer->setRotation( req->page()->orientation() * 90 ); + gsreq.rotation = req->page()->orientation() * 90; if (req->page()->rotation() == Okular::Rotation90 || req->page()->rotation() == Okular::Rotation270) { - renderer->setMagnify( qMax( (double)req->height() / req->page()->width(), - (double)req->width() / req->page()->height() ) ); + gsreq.magnify = qMax( (double)req->height() / req->page()->width(), + (double)req->width() / req->page()->height() ); } else { - renderer->setMagnify( qMax( (double)req->width() / req->page()->width(), - (double)req->height() / req->page()->height() ) ); + gsreq.magnify = qMax( (double)req->width() / req->page()->width(), + (double)req->height() / req->page()->height() ); } + gsreq.request = req; m_request = req; - renderer->startRequest(req, page); + renderer->addRequest(gsreq); } bool GSGenerator::canGeneratePixmap() const diff --git a/generators/spectre/rendererthread.cpp b/generators/spectre/rendererthread.cpp index 7d14be221..73f562560 100644 --- a/generators/spectre/rendererthread.cpp +++ b/generators/spectre/rendererthread.cpp @@ -35,30 +35,11 @@ GSRendererThread::~GSRendererThread() spectre_render_context_free(m_renderContext); } -void GSRendererThread::setMagnify(double magnify) +void GSRendererThread::addRequest(const GSRendererThreadRequest &req) { - spectre_render_context_set_scale(m_renderContext, magnify, magnify); -} - -void GSRendererThread::setPlatformFonts(bool pfonts) -{ - spectre_render_context_set_use_platform_fonts(m_renderContext, pfonts); -} - -void GSRendererThread::setAABits(int text, int graphics) -{ - spectre_render_context_set_antialias_bits(m_renderContext, graphics, text); -} - -void GSRendererThread::setRotation(int rotation) -{ - spectre_render_context_set_rotation(m_renderContext, rotation); -} - -void GSRendererThread::startRequest(Okular::PixmapRequest *request, SpectrePage *page) -{ - m_nextRequest = request; - m_nextPage = page; + m_queueMutex.lock(); + m_queue.enqueue(req); + m_queueMutex.unlock(); m_semaphore.release(); } @@ -67,41 +48,54 @@ void GSRendererThread::run() while(1) { m_semaphore.acquire(); - m_currentRequest = m_nextRequest; - m_currentPage = m_nextPage; - - unsigned char *data = NULL; - int row_length; - - int wantedWidth = m_currentRequest->width(); - int wantedHeight = m_currentRequest->height(); - - spectre_page_render(m_currentPage, m_renderContext, &data, &row_length); - - QImage img; - if (row_length == wantedWidth * 4) - { - img = QImage(data, wantedWidth, wantedHeight, QImage::Format_RGB32 ); - } - else - { - // In case this ends up beign very slow we can try with some memmove - QImage aux(data, row_length / 4, wantedHeight, QImage::Format_RGB32 ); - img = QImage(aux.copy(0, 0, wantedWidth, wantedHeight)); - } - QImage *image = new QImage(img.copy()); - free(data); - - if (image->width() != wantedWidth || image->height() != wantedHeight) + bool goAhead = true; + do { - kWarning(4711) << "Generated image does not match wanted size " << image->width() << " " << m_currentRequest->width() << " " << image->height() << " " << m_currentRequest->height() ; - QImage aux = image->scaled(wantedWidth, wantedHeight); - delete image; - image = new QImage(aux); - } - emit imageDone(image, m_currentRequest); - - spectre_page_free(m_currentPage); + m_queueMutex.lock(); + GSRendererThreadRequest req = m_queue.dequeue(); + goAhead = !m_queue.isEmpty(); + m_queueMutex.unlock(); + + spectre_render_context_set_scale(m_renderContext, req.magnify, req.magnify); + spectre_render_context_set_use_platform_fonts(m_renderContext, req.platformFonts); + spectre_render_context_set_antialias_bits(m_renderContext, req.graphicsAAbits, req.textAAbits); + spectre_render_context_set_rotation(m_renderContext, req.rotation); + + unsigned char *data = NULL; + int row_length = 0; + int wantedWidth = req.request->width(); + int wantedHeight = req.request->height(); + + spectre_page_render(req.spectrePage, m_renderContext, &data, &row_length); + + QImage img; + if (row_length == wantedWidth * 4) + { + img = QImage(data, wantedWidth, wantedHeight, QImage::Format_RGB32); + } + else + { + // In case this ends up beign very slow we can try with some memmove + QImage aux(data, row_length / 4, wantedHeight, QImage::Format_RGB32); + img = QImage(aux.copy(0, 0, wantedWidth, wantedHeight)); + } + QImage *image = new QImage(img.copy()); + free(data); + + if (image->width() != wantedWidth || image->height() != wantedHeight) + { + kWarning(4711).nospace() << "Generated image does not match wanted size: " + << "[" << image->width() << "x" << image->height() << "] vs requested " + << "[" << req.request->width() << "x" << req.request->height() << "]"; + QImage aux = image->scaled(wantedWidth, wantedHeight); + delete image; + image = new QImage(aux); + } + emit imageDone(image, req.request); + + spectre_page_free(req.spectrePage); + + } while (goAhead); } } diff --git a/generators/spectre/rendererthread.h b/generators/spectre/rendererthread.h index aaf58048a..878cca8df 100644 --- a/generators/spectre/rendererthread.h +++ b/generators/spectre/rendererthread.h @@ -10,6 +10,8 @@ #ifndef _OKULAR_GSRENDERERTHREAD_H_ #define _OKULAR_GSRENDERERTHREAD_H_ +#include +#include #include #include #include @@ -17,12 +19,37 @@ #include class QImage; +class GSGenerator; namespace Okular { class PixmapRequest; } +struct GSRendererThreadRequest +{ + GSRendererThreadRequest(GSGenerator *_owner) + : owner(_owner) + , request(0) + , spectrePage(0) + , textAAbits(1) + , graphicsAAbits(1) + , magnify(1.0) + , rotation(0) + , platformFonts(true) + {} + + GSGenerator *owner; + Okular::PixmapRequest *request; + SpectrePage *spectrePage; + int textAAbits; + int graphicsAAbits; + double magnify; + int rotation; + bool platformFonts; +}; +Q_DECLARE_TYPEINFO(GSRendererThreadRequest, Q_MOVABLE_TYPE); + class GSRendererThread : public QThread { Q_OBJECT @@ -31,12 +58,7 @@ Q_OBJECT ~GSRendererThread(); - void setPlatformFonts(bool pfonts); - void setAABits(int text, int graphics); - void setMagnify(double magnify); - void setRotation(int rotation); - - void startRequest(Okular::PixmapRequest *request, SpectrePage *page); + void addRequest(const GSRendererThreadRequest &req); signals: void imageDone(QImage *image, Okular::PixmapRequest *request); @@ -51,8 +73,8 @@ Q_OBJECT void run(); SpectreRenderContext *m_renderContext; - Okular::PixmapRequest *m_currentRequest, *m_nextRequest; - SpectrePage *m_currentPage, *m_nextPage; + QQueue m_queue; + QMutex m_queueMutex; }; #endif