Skip to content

Commit

Permalink
Use multiple threads to do rgba -> rgba RageSurface conversion.
Browse files Browse the repository at this point in the history
  • Loading branch information
xwidghet committed Jun 18, 2017
1 parent ee00e60 commit 35ccdfd
Showing 1 changed file with 91 additions and 19 deletions.
110 changes: 91 additions & 19 deletions src/RageSurfaceUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "RageUtil.h"
#include "RageLog.h"
#include "RageFile.h"
#include <thread>

uint32_t RageSurfaceUtils::decodepixel( const uint8_t *p, int bpp )
{
Expand Down Expand Up @@ -574,33 +575,104 @@ static bool blit_rgba_to_rgba( const RageSurface *src_surf, const RageSurface *d
lookup[c][i] = (uint8_t) SCALE( i, 0, max_src_val, 0, max_dst_val );
}
}

// Use multiple threads to do in-place pixel conversion
unsigned int numThreads = max(std::thread::hardware_concurrency(), 2u)/2;
size_t segmentSize = height / numThreads;
std::vector<std::thread> threads;
threads.reserve(numThreads);

for (int curThread = 0; curThread < numThreads; ++curThread)
{
threads.push_back(std::thread([&, curThread] {
int startingPoint = segmentSize*curThread;
int localHeight = segmentSize + segmentSize*curThread;
int localEnd = localHeight - segmentSize;

auto localSrc = src;
auto localDst = dst;

// Skip pixels until we arrive at this thread's starting point
// -
// handle width
localSrc += src_surf->format->BytesPerPixel*width*startingPoint;
localDst += dst_surf->format->BytesPerPixel*width*startingPoint;
// handle height
localSrc += srcskip*startingPoint;
localDst += dstskip*startingPoint;

while (localHeight-- > localEnd)
{
int x = 0;
while (x++ < width)
{
unsigned int pixel = RageSurfaceUtils::decodepixel(localSrc, src_surf->format->BytesPerPixel);

while( height-- )
// Convert pixel to the destination format.
unsigned int opixel = 0;
for (int c = 0; c < 4; ++c)
{
int lSrc = (pixel & src_masks[c]) >> src_shifts[c];
opixel |= lookup[c][lSrc] << dst_shifts[c];
}

// Store it.
RageSurfaceUtils::encodepixel(localDst, dst_surf->format->BytesPerPixel, opixel);

localSrc += src_surf->format->BytesPerPixel;
localDst += dst_surf->format->BytesPerPixel;
}

localSrc += srcskip;
localDst += dstskip;
}
}));
}

for (auto& t : threads)
t.join();

// Convert any left over pixels
int endHeight = segmentSize + segmentSize*(numThreads-1);
if (endHeight < height)
{
int x = 0;
while( x++ < width )
int startingPoint = segmentSize*numThreads;
// Skip pixels until we arrive at this thread's starting point
// -
// handle width
src += src_surf->format->BytesPerPixel*width*startingPoint;
dst += dst_surf->format->BytesPerPixel*width*startingPoint;
// handle height
src += srcskip*startingPoint;
dst += dstskip*startingPoint;

while (height-- > endHeight)
{
unsigned int pixel = RageSurfaceUtils::decodepixel( src, src_surf->format->BytesPerPixel );

// Convert pixel to the destination format.
unsigned int opixel = 0;
for( int c = 0; c < 4; ++c )
int x = 0;
while (x++ < width)
{
int lSrc = (pixel & src_masks[c]) >> src_shifts[c];
opixel |= lookup[c][lSrc] << dst_shifts[c];
}
unsigned int pixel = RageSurfaceUtils::decodepixel(src, src_surf->format->BytesPerPixel);

// Store it.
RageSurfaceUtils::encodepixel( dst, dst_surf->format->BytesPerPixel, opixel );
// Convert pixel to the destination format.
unsigned int opixel = 0;
for (int c = 0; c < 4; ++c)
{
int lSrc = (pixel & src_masks[c]) >> src_shifts[c];
opixel |= lookup[c][lSrc] << dst_shifts[c];
}

src += src_surf->format->BytesPerPixel;
dst += dst_surf->format->BytesPerPixel;
}
// Store it.
RageSurfaceUtils::encodepixel(dst, dst_surf->format->BytesPerPixel, opixel);

src += srcskip;
dst += dstskip;
}
src += src_surf->format->BytesPerPixel;
dst += dst_surf->format->BytesPerPixel;
}

src += srcskip;
dst += dstskip;
}
}

return true;
}

Expand Down

0 comments on commit 35ccdfd

Please sign in to comment.