WIP on canvas pixel shading
This commit is contained in:
parent
fb3d32baf4
commit
2aeecdec62
24 changed files with 317 additions and 83 deletions
|
@ -99,3 +99,8 @@ void CanvasPixel::updateComposite()
|
|||
}
|
||||
composite = result;
|
||||
}
|
||||
|
||||
void CanvasPixel::setComposite(const Color &color)
|
||||
{
|
||||
composite = color;
|
||||
}
|
||||
|
|
|
@ -22,11 +22,13 @@ public:
|
|||
|
||||
inline int getFragmentCount() const {return count;}
|
||||
inline const Color &getComposite() const {return composite;}
|
||||
inline const CanvasFragment &getFragment(int position) const {return fragments[position];}
|
||||
const CanvasFragment *getFrontFragment() const;
|
||||
|
||||
void reset();
|
||||
void pushFragment(const CanvasFragment &fragment);
|
||||
void updateComposite();
|
||||
void setComposite(const Color &color);
|
||||
|
||||
private:
|
||||
int count;
|
||||
|
|
36
src/render/software/CanvasPixelShader.cpp
Normal file
36
src/render/software/CanvasPixelShader.cpp
Normal file
|
@ -0,0 +1,36 @@
|
|||
#include "CanvasPixelShader.h"
|
||||
|
||||
#include "Color.h"
|
||||
#include "SoftwareCanvasRenderer.h"
|
||||
#include "CanvasPortion.h"
|
||||
#include "CanvasPixel.h"
|
||||
#include "CanvasFragment.h"
|
||||
#include "Rasterizer.h"
|
||||
|
||||
CanvasPixelShader::CanvasPixelShader(const SoftwareCanvasRenderer &renderer, CanvasPortion *portion, int chunk_size, int chunks_x, int chunks_y):
|
||||
renderer(renderer), portion(portion), chunk_size(chunk_size), chunks_x(chunks_x), chunks_y(chunks_y)
|
||||
{
|
||||
}
|
||||
|
||||
int CanvasPixelShader::processParallelUnit(int unit)
|
||||
{
|
||||
// Locate the chunk we work on
|
||||
int chunk_x = unit % chunks_x;
|
||||
int chunk_y = unit / chunks_x;
|
||||
|
||||
// Resolve the pixel color
|
||||
int x = chunk_x * chunk_size;
|
||||
int y = chunk_y * chunk_size;
|
||||
const CanvasPixel &pixel = portion->at(x, y);
|
||||
int n = pixel.getFragmentCount();
|
||||
Color composite = COLOR_BLACK;
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
const CanvasFragment &fragment = pixel.getFragment(i);
|
||||
const Rasterizer &rasterizer = renderer.getRasterizer(fragment.getClient());
|
||||
composite.mask(rasterizer.shadeFragment(fragment));
|
||||
}
|
||||
portion->setColor(x, y, composite);
|
||||
|
||||
return 0;
|
||||
}
|
36
src/render/software/CanvasPixelShader.h
Normal file
36
src/render/software/CanvasPixelShader.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
#ifndef CANVASPIXELSHADER_H
|
||||
#define CANVASPIXELSHADER_H
|
||||
|
||||
#include "software_global.h"
|
||||
|
||||
#include "ParallelWorker.h"
|
||||
|
||||
namespace paysages {
|
||||
namespace software {
|
||||
|
||||
/**
|
||||
* @brief Parallel worker that can work on canvas portion to resolve pixel colors.
|
||||
*
|
||||
* This is used after the rasterization phase to compute pixel colors from the fragments stored in them.
|
||||
*
|
||||
* This worker will be set to work on a given chunk of a canvas portion.
|
||||
*/
|
||||
class CanvasPixelShader: public ParallelWorker
|
||||
{
|
||||
public:
|
||||
CanvasPixelShader(const SoftwareCanvasRenderer &renderer, CanvasPortion *portion, int chunk_size, int chunks_x, int chunks_y);
|
||||
|
||||
virtual int processParallelUnit(int unit);
|
||||
|
||||
private:
|
||||
const SoftwareCanvasRenderer &renderer;
|
||||
CanvasPortion *portion;
|
||||
int chunk_size;
|
||||
int chunks_x;
|
||||
int chunks_y;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // CANVASPIXELSHADER_H
|
|
@ -69,3 +69,25 @@ void CanvasPortion::pushFragment(int x, int y, const CanvasFragment &fragment)
|
|||
preview->pushPixel(x, y, old_color, pixel.getComposite());
|
||||
}
|
||||
}
|
||||
|
||||
const CanvasPixel &CanvasPortion::at(int x, int y)
|
||||
{
|
||||
CHECK_COORDINATES();
|
||||
|
||||
return pixels[y * width + x];
|
||||
}
|
||||
|
||||
void CanvasPortion::setColor(int x, int y, const Color &color)
|
||||
{
|
||||
CHECK_COORDINATES();
|
||||
|
||||
CanvasPixel &pixel = pixels[y * width + x];
|
||||
Color old_color = pixel.getComposite();
|
||||
|
||||
pixel.setComposite(color);
|
||||
|
||||
if (preview)
|
||||
{
|
||||
preview->pushPixel(x, y, old_color, pixel.getComposite());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ namespace paysages {
|
|||
namespace software {
|
||||
|
||||
/**
|
||||
* @brief Rectangular portion of a Canvas.
|
||||
* Rectangular portion of a Canvas.
|
||||
*
|
||||
* Contains the pixels of a canvas region (CanvasPixel).
|
||||
*/
|
||||
|
@ -26,12 +26,26 @@ public:
|
|||
void setSize(int width, int height);
|
||||
|
||||
/**
|
||||
* @brief Add a fragment to the pixel located at (x, y).
|
||||
* Add a fragment to the pixel located at (x, y).
|
||||
*
|
||||
* Checking x and y coordinates to be in the canvas portion should be done before this call.
|
||||
*/
|
||||
void pushFragment(int x, int y, const CanvasFragment &fragment);
|
||||
|
||||
/**
|
||||
* Get the CanvasPixel at a given coordinates.
|
||||
*
|
||||
* Checking x and y coordinates to be in the canvas portion should be done before this call.
|
||||
*/
|
||||
const CanvasPixel &at(int x, int y);
|
||||
|
||||
/**
|
||||
* Change the final color of the pixel.
|
||||
*
|
||||
* Checking x and y coordinates to be in the canvas portion should be done before this call.
|
||||
*/
|
||||
void setColor(int x, int y, const Color &color);
|
||||
|
||||
private:
|
||||
int width;
|
||||
int height;
|
||||
|
|
|
@ -136,10 +136,6 @@ void Rasterizer::pushDisplacedQuad(CanvasPortion *canvas, const Vector3 &v1, con
|
|||
pushDisplacedTriangle(canvas, v4, v1, v3, ov4, ov1, ov3);
|
||||
}
|
||||
|
||||
void Rasterizer::rasterizeToCanvas(CanvasPortion *)
|
||||
{
|
||||
}
|
||||
|
||||
void Rasterizer::scanGetDiff(ScanPoint* v1, ScanPoint* v2, ScanPoint* result)
|
||||
{
|
||||
result->pixel.x = v2->pixel.x - v1->pixel.x;
|
||||
|
@ -316,25 +312,35 @@ void Rasterizer::renderScanLines(CanvasPortion *canvas, RenderScanlines* scanlin
|
|||
current.x = x;
|
||||
for (cury = starty; cury <= endy; cury++)
|
||||
{
|
||||
fy = (double)cury + 0.5;
|
||||
if (fy < down.pixel.y)
|
||||
if (dy == 0)
|
||||
{
|
||||
fy = down.pixel.y;
|
||||
// Down and up are the same
|
||||
current = down;
|
||||
}
|
||||
else if (fy > up.pixel.y)
|
||||
else
|
||||
{
|
||||
fy = up.pixel.y;
|
||||
}
|
||||
fy = fy - down.pixel.y;
|
||||
fy = (double)cury + 0.5;
|
||||
if (fy < down.pixel.y)
|
||||
{
|
||||
fy = down.pixel.y;
|
||||
}
|
||||
else if (fy > up.pixel.y)
|
||||
{
|
||||
fy = up.pixel.y;
|
||||
}
|
||||
fy = fy - down.pixel.y;
|
||||
|
||||
current.y = cury;
|
||||
scanInterpolate(renderer->render_camera, &down, &diff, fy / dy, ¤t);
|
||||
current.y = cury;
|
||||
scanInterpolate(renderer->render_camera, &down, &diff, fy / dy, ¤t);
|
||||
}
|
||||
|
||||
CanvasFragment fragment(current.pixel.z, Vector3(current.location.x, current.location.y, current.location.z), current.client);
|
||||
|
||||
Color frag_color = *color;
|
||||
if (cury == starty || cury == endy)
|
||||
{
|
||||
frag_color.mask(Color(0.0, 0.0, 0.0, 0.3));
|
||||
}
|
||||
fragment.setColor(frag_color);
|
||||
|
||||
canvas->pushFragment(current.x, current.y, fragment);
|
||||
|
|
|
@ -20,7 +20,8 @@ public:
|
|||
|
||||
inline SoftwareRenderer *getRenderer() const {return renderer;}
|
||||
|
||||
virtual void rasterizeToCanvas(CanvasPortion* canvas);
|
||||
virtual void rasterizeToCanvas(CanvasPortion* canvas) = 0;
|
||||
virtual Color shadeFragment(const CanvasFragment &fragment) const = 0;
|
||||
|
||||
protected:
|
||||
void pushProjectedTriangle(CanvasPortion *canvas, const Vector3 &pixel1, const Vector3 &pixel2, const Vector3 &pixel3, const Vector3 &location1, const Vector3 &location2, const Vector3 &location3);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "AtmosphereResult.h"
|
||||
#include "CloudsRenderer.h"
|
||||
#include "Rasterizer.h"
|
||||
#include "CanvasFragment.h"
|
||||
|
||||
#define SPHERE_SIZE 20000.0
|
||||
|
||||
|
@ -15,21 +16,6 @@ SkyRasterizer::SkyRasterizer(SoftwareRenderer* renderer, int client_id):
|
|||
{
|
||||
}
|
||||
|
||||
static Color _postProcessFragment(SoftwareRenderer* renderer, const Vector3 &location, void*)
|
||||
{
|
||||
Vector3 camera_location, direction;
|
||||
Color result;
|
||||
|
||||
camera_location = renderer->getCameraLocation(location);
|
||||
direction = location.sub(camera_location);
|
||||
|
||||
/* TODO Don't compute result->color if it's fully covered by clouds */
|
||||
result = renderer->getAtmosphereRenderer()->getSkyColor(direction.normalize()).final;
|
||||
result = renderer->getCloudsRenderer()->getColor(camera_location, camera_location.add(direction.scale(10.0)), result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void SkyRasterizer::rasterizeToCanvas(CanvasPortion* canvas)
|
||||
{
|
||||
int res_i, res_j;
|
||||
|
@ -84,3 +70,19 @@ void SkyRasterizer::rasterizeToCanvas(CanvasPortion* canvas)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
Color SkyRasterizer::shadeFragment(const CanvasFragment &fragment) const
|
||||
{
|
||||
Vector3 location = fragment.getLocation();
|
||||
Vector3 camera_location, direction;
|
||||
Color result;
|
||||
|
||||
camera_location = renderer->getCameraLocation(location);
|
||||
direction = location.sub(camera_location);
|
||||
|
||||
/* TODO Don't compute result->color if it's fully covered by clouds */
|
||||
result = renderer->getAtmosphereRenderer()->getSkyColor(direction.normalize()).final;
|
||||
result = renderer->getCloudsRenderer()->getColor(camera_location, camera_location.add(direction.scale(10.0)), result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ public:
|
|||
SkyRasterizer(SoftwareRenderer* renderer, int client_id);
|
||||
|
||||
virtual void rasterizeToCanvas(CanvasPortion* canvas);
|
||||
virtual Color shadeFragment(const CanvasFragment &fragment) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
#include "WaterRasterizer.h"
|
||||
#include "SkyRasterizer.h"
|
||||
#include "CameraDefinition.h"
|
||||
#include "ParallelWork.h"
|
||||
#include "CanvasPortion.h"
|
||||
#include "CanvasPixelShader.h"
|
||||
|
||||
SoftwareCanvasRenderer::SoftwareCanvasRenderer()
|
||||
{
|
||||
|
@ -58,6 +61,11 @@ const std::vector<Rasterizer *> &SoftwareCanvasRenderer::getRasterizers() const
|
|||
return rasterizers;
|
||||
}
|
||||
|
||||
const Rasterizer &SoftwareCanvasRenderer::getRasterizer(int client_id) const
|
||||
{
|
||||
return *(getRasterizers()[client_id]);
|
||||
}
|
||||
|
||||
void SoftwareCanvasRenderer::rasterize(CanvasPortion *portion, bool threaded)
|
||||
{
|
||||
for (auto &rasterizer:getRasterizers())
|
||||
|
@ -68,5 +76,14 @@ void SoftwareCanvasRenderer::rasterize(CanvasPortion *portion, bool threaded)
|
|||
|
||||
void SoftwareCanvasRenderer::postProcess(CanvasPortion *portion, bool threaded)
|
||||
{
|
||||
// TODO
|
||||
// Subdivide in chunks
|
||||
int chunk_size = 32;
|
||||
int chunks_x = portion->getWidth() / chunk_size + 1;
|
||||
int chunks_y = portion->getHeight() / chunk_size + 1;
|
||||
int units = chunks_x * chunks_y;
|
||||
|
||||
// Render chunks in parallel
|
||||
CanvasPixelShader shader(*this, portion, chunk_size, chunks_x, chunks_y);
|
||||
ParallelWork work(&shader, units);
|
||||
work.perform();
|
||||
}
|
||||
|
|
|
@ -36,11 +36,16 @@ public:
|
|||
*/
|
||||
void render();
|
||||
|
||||
/*!
|
||||
* \brief Get the list of objects that can be rasterized to polygons on a canvas.
|
||||
/**
|
||||
* @brief Get the list of objects that can be rasterized to polygons on a canvas.
|
||||
*/
|
||||
virtual const std::vector<Rasterizer*> &getRasterizers() const;
|
||||
|
||||
/**
|
||||
* Get a rasterizer by its client id.
|
||||
*/
|
||||
const Rasterizer &getRasterizer(int client_id) const;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Rasterize the scenery into a canvas portion.
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "Scenery.h"
|
||||
#include "ParallelQueue.h"
|
||||
#include "CanvasPortion.h"
|
||||
#include "CanvasFragment.h"
|
||||
|
||||
TerrainRasterizer::TerrainRasterizer(SoftwareRenderer* renderer, int client_id):
|
||||
Rasterizer(renderer, client_id, Color(0.5, 0.3, 0.3))
|
||||
|
@ -20,12 +21,6 @@ static inline Vector3 _getPoint(SoftwareRenderer* renderer, double x, double z)
|
|||
return Vector3(x, renderer->getTerrainRenderer()->getHeight(x, z, 1), z);
|
||||
}
|
||||
|
||||
static Color _postProcessFragment(SoftwareRenderer* renderer, const Vector3 &point, void*)
|
||||
{
|
||||
double precision = renderer->getPrecision(_getPoint(renderer, point.x, point.z));
|
||||
return renderer->getTerrainRenderer()->getFinalColor(point, precision);
|
||||
}
|
||||
|
||||
void TerrainRasterizer::tessellateChunk(CanvasPortion* canvas, TerrainChunkInfo* chunk, int detail)
|
||||
{
|
||||
if (detail < 1)
|
||||
|
@ -245,3 +240,10 @@ void TerrainRasterizer::rasterizeToCanvas(CanvasPortion *canvas)
|
|||
|
||||
queue->wait();
|
||||
}
|
||||
|
||||
Color TerrainRasterizer::shadeFragment(const CanvasFragment &fragment) const
|
||||
{
|
||||
Vector3 point = fragment.getLocation();
|
||||
double precision = renderer->getPrecision(_getPoint(renderer, point.x, point.z));
|
||||
return renderer->getTerrainRenderer()->getFinalColor(point, precision);
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ public:
|
|||
virtual void rasterize();
|
||||
|
||||
virtual void rasterizeToCanvas(CanvasPortion* canvas);
|
||||
virtual Color shadeFragment(const CanvasFragment &fragment) const;
|
||||
|
||||
private:
|
||||
ParallelQueue* queue;
|
||||
|
|
|
@ -3,17 +3,13 @@
|
|||
#include "SoftwareRenderer.h"
|
||||
#include "WaterRenderer.h"
|
||||
#include "ParallelQueue.h"
|
||||
#include "CanvasFragment.h"
|
||||
|
||||
WaterRasterizer::WaterRasterizer(SoftwareRenderer* renderer, int client_id):
|
||||
Rasterizer(renderer, client_id, Color(0.1, 0.3, 0.6))
|
||||
{
|
||||
}
|
||||
|
||||
static Color _postProcessFragment(SoftwareRenderer* renderer, const Vector3 &location, void*)
|
||||
{
|
||||
return renderer->getWaterRenderer()->getResult(location.x, location.z).final;
|
||||
}
|
||||
|
||||
static inline Vector3 _getFirstPassVertex(SoftwareRenderer* renderer, double x, double z)
|
||||
{
|
||||
Vector3 result;
|
||||
|
@ -84,3 +80,9 @@ void WaterRasterizer::rasterizeToCanvas(CanvasPortion *canvas)
|
|||
radius_ext += chunk_size;
|
||||
}
|
||||
}
|
||||
|
||||
Color WaterRasterizer::shadeFragment(const CanvasFragment &fragment) const
|
||||
{
|
||||
Vector3 location = fragment.getLocation();
|
||||
return renderer->getWaterRenderer()->getResult(location.x, location.z).final;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ public:
|
|||
void rasterizeQuad(CanvasPortion* canvas, double x, double z, double size);
|
||||
|
||||
virtual void rasterizeToCanvas(CanvasPortion* canvas);
|
||||
virtual Color shadeFragment(const CanvasFragment &fragment) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -45,7 +45,8 @@ SOURCES += SoftwareRenderer.cpp \
|
|||
Rasterizer.cpp \
|
||||
CanvasLiveClient.cpp \
|
||||
CanvasPreview.cpp \
|
||||
RenderConfig.cpp
|
||||
RenderConfig.cpp \
|
||||
CanvasPixelShader.cpp
|
||||
|
||||
HEADERS += SoftwareRenderer.h\
|
||||
software_global.h \
|
||||
|
@ -80,7 +81,8 @@ HEADERS += SoftwareRenderer.h\
|
|||
Rasterizer.h \
|
||||
CanvasLiveClient.h \
|
||||
CanvasPreview.h \
|
||||
RenderConfig.h
|
||||
RenderConfig.h \
|
||||
CanvasPixelShader.h
|
||||
|
||||
unix:!symbian {
|
||||
maemo5 {
|
||||
|
|
|
@ -53,6 +53,7 @@ namespace software {
|
|||
class CanvasFragment;
|
||||
class CanvasLiveClient;
|
||||
class CanvasPreview;
|
||||
class CanvasPixelShader;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,37 +2,72 @@
|
|||
|
||||
#include "Thread.h"
|
||||
#include "System.h"
|
||||
#include "ParallelWorker.h"
|
||||
#include <cassert>
|
||||
|
||||
/**
|
||||
* Compatibility class for code that uses ParallelUnitFunction.
|
||||
*/
|
||||
class ParallelWorkerCompat:public ParallelWorker
|
||||
{
|
||||
public:
|
||||
ParallelWorkerCompat(ParallelWork *work, ParallelWork::ParallelUnitFunction func, void* data):
|
||||
ParallelWorker(), work(work), func(func), data(data)
|
||||
{
|
||||
}
|
||||
|
||||
virtual int processParallelUnit(int unit)
|
||||
{
|
||||
return func(work, unit, data);
|
||||
}
|
||||
|
||||
private:
|
||||
ParallelWork* work;
|
||||
ParallelWork::ParallelUnitFunction func;
|
||||
void* data;
|
||||
};
|
||||
|
||||
ParallelWork::ParallelWork(ParallelWorker *worker, int units)
|
||||
{
|
||||
this->units = units;
|
||||
this->running = 0;
|
||||
this->worker = worker;
|
||||
this->worker_compat = false;
|
||||
}
|
||||
|
||||
ParallelWork::ParallelWork(ParallelUnitFunction func, int units, void* data)
|
||||
{
|
||||
this->units = units;
|
||||
this->running = 0;
|
||||
this->unit_function = func;
|
||||
this->data = data;
|
||||
this->worker = new ParallelWorkerCompat(this, func, data);
|
||||
this->worker_compat = true;
|
||||
}
|
||||
|
||||
ParallelWork::~ParallelWork()
|
||||
{
|
||||
assert(not running);
|
||||
if (worker_compat)
|
||||
{
|
||||
delete worker;
|
||||
}
|
||||
}
|
||||
|
||||
static void* _workerThreadCallback(ParallelWork::ParallelWorker* worker)
|
||||
static void* _workerThreadCallback(ParallelWork::ParallelWorkerThread* thread)
|
||||
{
|
||||
worker->result = worker->work->unit_function(worker->work, worker->unit, worker->work->data);
|
||||
worker->status = ParallelWork::PARALLEL_WORKER_STATUS_DONE;
|
||||
thread->result = thread->worker->processParallelUnit(thread->unit);
|
||||
thread->status = ParallelWork::PARALLEL_WORKER_STATUS_DONE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int _runNextWorker(ParallelWork::ParallelWorker workers[], int worker_count, int unit)
|
||||
static int _runNextWorker(ParallelWork::ParallelWorkerThread threads[], int thread_count, int unit)
|
||||
{
|
||||
int i;
|
||||
|
||||
while (1)
|
||||
{
|
||||
for (i = 0; i < worker_count; i++)
|
||||
for (i = 0; i < thread_count; i++)
|
||||
{
|
||||
ParallelWork::ParallelWorker* worker = workers + i;
|
||||
ParallelWork::ParallelWorkerThread* worker = threads + i;
|
||||
if (worker->status == ParallelWork::PARALLEL_WORKER_STATUS_VOID)
|
||||
{
|
||||
worker->status = ParallelWork::PARALLEL_WORKER_STATUS_RUNNING;
|
||||
|
@ -62,47 +97,47 @@ static int _runNextWorker(ParallelWork::ParallelWorker workers[], int worker_cou
|
|||
}
|
||||
}
|
||||
|
||||
int ParallelWork::perform(int nbworkers)
|
||||
int ParallelWork::perform(int thread_count)
|
||||
{
|
||||
int i, done, result;
|
||||
assert(not running);
|
||||
|
||||
result = 0;
|
||||
|
||||
if (nbworkers <= 0)
|
||||
if (thread_count <= 0)
|
||||
{
|
||||
nbworkers = System::getCoreCount();
|
||||
thread_count = System::getCoreCount();
|
||||
}
|
||||
if (nbworkers > PARALLEL_MAX_THREADS)
|
||||
if (thread_count > PARALLEL_MAX_THREADS)
|
||||
{
|
||||
nbworkers = PARALLEL_MAX_THREADS;
|
||||
thread_count = PARALLEL_MAX_THREADS;
|
||||
}
|
||||
running = 1;
|
||||
|
||||
/* Init workers */
|
||||
for (i = 0; i < nbworkers; i++)
|
||||
for (i = 0; i < thread_count; i++)
|
||||
{
|
||||
workers[i].status = PARALLEL_WORKER_STATUS_VOID;
|
||||
workers[i].work = this;
|
||||
threads[i].status = PARALLEL_WORKER_STATUS_VOID;
|
||||
threads[i].worker = worker;
|
||||
}
|
||||
|
||||
/* Perform run */
|
||||
for (done = 0; done < units; done++)
|
||||
{
|
||||
if (_runNextWorker(workers, nbworkers, done))
|
||||
if (_runNextWorker(threads, thread_count, done))
|
||||
{
|
||||
result++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait and clean up workers */
|
||||
for (i = 0; i < nbworkers; i++)
|
||||
for (i = 0; i < thread_count; i++)
|
||||
{
|
||||
if (workers[i].status != PARALLEL_WORKER_STATUS_VOID)
|
||||
if (threads[i].status != PARALLEL_WORKER_STATUS_VOID)
|
||||
{
|
||||
workers[i].thread->join();
|
||||
delete workers[i].thread;
|
||||
if (workers[i].result)
|
||||
threads[i].thread->join();
|
||||
delete threads[i].thread;
|
||||
if (threads[i].result)
|
||||
{
|
||||
result++;
|
||||
}
|
||||
|
|
|
@ -23,22 +23,24 @@ public:
|
|||
typedef struct
|
||||
{
|
||||
Thread* thread;
|
||||
ParallelWork* work;
|
||||
ParallelWorker* worker;
|
||||
ParallelWorkerStatus status;
|
||||
int unit;
|
||||
int result;
|
||||
} ParallelWorker;
|
||||
} ParallelWorkerThread;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Create a parallel work handler.
|
||||
*
|
||||
* This will spawn an optimal number of threads to process a given number of work units.
|
||||
* This will spawn a number of threads.
|
||||
*/
|
||||
ParallelWork(ParallelWorker *worker, int units);
|
||||
|
||||
/**
|
||||
* Create a parallel work handler.
|
||||
*
|
||||
* @param func The callback that will be called from threads to process one unit.
|
||||
* @param units Number of units to handle.
|
||||
* @param data Custom data that will be passed to the callback.
|
||||
* @return The newly allocated handler.
|
||||
* This is a compatibility constructor for older code, use the constructor with ParallelWorker instead.
|
||||
*/
|
||||
ParallelWork(ParallelUnitFunction func, int units, void* data);
|
||||
|
||||
|
@ -52,15 +54,15 @@ public:
|
|||
/**
|
||||
* Start working on the units.
|
||||
*
|
||||
* @param workers Number of threads to spaws, -1 for an optimal number.
|
||||
* @param threads Number of threads to spaws, -1 for an optimal number.
|
||||
*/
|
||||
int perform(int workers=-1);
|
||||
int perform(int thread_count=-1);
|
||||
|
||||
int units;
|
||||
int running;
|
||||
ParallelUnitFunction unit_function;
|
||||
ParallelWorker workers[PARALLEL_MAX_THREADS];
|
||||
void* data;
|
||||
ParallelWorker *worker;
|
||||
bool worker_compat;
|
||||
ParallelWorkerThread threads[PARALLEL_MAX_THREADS];
|
||||
};
|
||||
|
||||
}
|
||||
|
|
9
src/system/ParallelWorker.cpp
Normal file
9
src/system/ParallelWorker.cpp
Normal file
|
@ -0,0 +1,9 @@
|
|||
#include "ParallelWorker.h"
|
||||
|
||||
ParallelWorker::ParallelWorker()
|
||||
{
|
||||
}
|
||||
|
||||
ParallelWorker::~ParallelWorker()
|
||||
{
|
||||
}
|
29
src/system/ParallelWorker.h
Normal file
29
src/system/ParallelWorker.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
#ifndef PARALLELWORKER_H
|
||||
#define PARALLELWORKER_H
|
||||
|
||||
#include "system_global.h"
|
||||
|
||||
namespace paysages {
|
||||
namespace system {
|
||||
|
||||
/**
|
||||
* @brief Worker that can be used by the ParallelWork object to perform tasks in several threads.
|
||||
*/
|
||||
class SYSTEMSHARED_EXPORT ParallelWorker
|
||||
{
|
||||
public:
|
||||
ParallelWorker();
|
||||
virtual ~ParallelWorker();
|
||||
|
||||
/**
|
||||
* Abstract method to reimplement to process a work unit.
|
||||
*
|
||||
* This method will be called from any thread in the thread pool used by the ParallelWork.
|
||||
*/
|
||||
virtual int processParallelUnit(int unit) = 0;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // PARALLELWORKER_H
|
|
@ -25,7 +25,8 @@ SOURCES += \
|
|||
CacheFile.cpp \
|
||||
PictureWriter.cpp \
|
||||
Logs.cpp \
|
||||
ParallelPool.cpp
|
||||
ParallelPool.cpp \
|
||||
ParallelWorker.cpp
|
||||
|
||||
HEADERS += \
|
||||
system_global.h \
|
||||
|
@ -40,7 +41,8 @@ HEADERS += \
|
|||
CacheFile.h \
|
||||
PictureWriter.h \
|
||||
Logs.h \
|
||||
ParallelPool.h
|
||||
ParallelPool.h \
|
||||
ParallelWorker.h
|
||||
|
||||
unix:!symbian {
|
||||
maemo5 {
|
||||
|
|
|
@ -18,6 +18,7 @@ namespace system {
|
|||
class ParallelQueue;
|
||||
class ParallelWork;
|
||||
class ParallelPool;
|
||||
class ParallelWorker;
|
||||
class Thread;
|
||||
class Mutex;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue