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
remotes/origin/KDE/4.4
Pino Toscano 17 years ago
parent d6d9ff0e5c
commit a5564fa6dd
  1. 21
      generators/spectre/generator_ghostview.cpp
  2. 108
      generators/spectre/rendererthread.cpp
  3. 38
      generators/spectre/rendererthread.h

@ -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

@ -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);
}
}

@ -10,6 +10,8 @@
#ifndef _OKULAR_GSRENDERERTHREAD_H_
#define _OKULAR_GSRENDERERTHREAD_H_
#include <qmutex.h>
#include <qqueue.h>
#include <qsemaphore.h>
#include <qstring.h>
#include <qthread.h>
@ -17,12 +19,37 @@
#include <libspectre/spectre.h>
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<GSRendererThreadRequest> m_queue;
QMutex m_queueMutex;
};
#endif

Loading…
Cancel
Save