d0177f4c52
Fixed segfault bug in transform32_mmx.
1806 lines
46 KiB
C
1806 lines
46 KiB
C
#include "renpy.h"
|
|
#include <pygame/pygame.h>
|
|
#include "IMG_savepng.h"
|
|
#include <stdio.h>
|
|
#include <math.h>
|
|
|
|
#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
|
#define GCC_MMX 1
|
|
#include "mmx.h"
|
|
#endif
|
|
|
|
|
|
// Shows how to do this.
|
|
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
|
#endif
|
|
|
|
/* Initializes the stuff found in this file.
|
|
*/
|
|
void core_init() {
|
|
import_pygame_base();
|
|
import_pygame_surface();
|
|
}
|
|
|
|
void save_png_core(PyObject *pysurf, SDL_RWops *rw, int compress) {
|
|
SDL_Surface *surf;
|
|
|
|
surf = PySurface_AsSurface(pysurf);
|
|
|
|
/* Can't release GIL, since we're not using threaded RWops. */
|
|
IMG_SavePNG_RW(rw, surf, compress);
|
|
}
|
|
|
|
|
|
/* This pixellates a 32-bit RGBA pygame surface to a destination
|
|
* surface of a given size.
|
|
*
|
|
* pysrc - The source pygame surface, which must be 32-bit RGBA.
|
|
* pydst - The destination pygame surface, which should be 32-bit
|
|
* RGBA, and locked.
|
|
* avgwidth - The width of the pixels that will be averaged together.
|
|
* avgheight - The height of the pixels that will be averaged
|
|
* together.
|
|
* outwidth - The width of pixels that will be written to the output.
|
|
* outheight - The height of pixels that will be written to the
|
|
* output.
|
|
*
|
|
* We assume that pysrc and pydst have been locked before we are called.
|
|
*/
|
|
void pixellate32_core(PyObject *pysrc,
|
|
PyObject *pydst,
|
|
int avgwidth,
|
|
int avgheight,
|
|
int outwidth,
|
|
int outheight
|
|
) {
|
|
|
|
SDL_Surface *src;
|
|
SDL_Surface *dst;
|
|
|
|
int x, y, i, j;
|
|
Uint32 srcpitch, dstpitch;
|
|
Uint32 srcw, srch;
|
|
Uint32 dstw, dsth;
|
|
int vw, vh;
|
|
|
|
unsigned char *srcpixels;
|
|
unsigned char *dstpixels;
|
|
|
|
src = PySurface_AsSurface(pysrc);
|
|
dst = PySurface_AsSurface(pydst);
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
|
|
srcpixels = (unsigned char *) src->pixels;
|
|
dstpixels = (unsigned char *) dst->pixels;
|
|
srcpitch = src->pitch;
|
|
dstpitch = dst->pitch;
|
|
srcw = src->w;
|
|
dstw = dst->w;
|
|
srch = src->h;
|
|
dsth = dst->h;
|
|
|
|
/* Compute the virtual width and height. */
|
|
vw = ( srcw + avgwidth - 1) / avgwidth;
|
|
vh = ( srch + avgheight - 1) / avgheight;
|
|
|
|
/* Iterate through each of the virtual pixels. */
|
|
|
|
for (y = 0; y < vh; y++) {
|
|
int srcy = avgheight * y;
|
|
int dsty = outheight * y;
|
|
|
|
int srcylimit = srcy + avgheight;
|
|
int dstylimit = dsty + outheight;
|
|
|
|
if (srcylimit > srch) {
|
|
srcylimit = srch;
|
|
}
|
|
|
|
if (dstylimit > dsth) {
|
|
dstylimit = dsth;
|
|
}
|
|
|
|
for (x = 0; x < vw; x++) {
|
|
int srcx = avgwidth * x;
|
|
int dstx = outwidth * x;
|
|
|
|
int srcxlimit = srcx + avgwidth;
|
|
int dstxlimit = dstx + outheight;
|
|
|
|
if (srcxlimit > srcw) {
|
|
srcxlimit = srcw;
|
|
}
|
|
|
|
if (dstxlimit > dstw) {
|
|
dstxlimit = dstw;
|
|
}
|
|
|
|
// Please note that these names are just
|
|
// suggestions... It's possible that alpha will be
|
|
// in r, for example.
|
|
int r = 0;
|
|
int g = 0;
|
|
int b = 0;
|
|
int a = 0;
|
|
|
|
int number = 0;
|
|
|
|
// pos always points to the start of the current line.
|
|
unsigned char *pos = &srcpixels[srcy * srcpitch + srcx * 4];
|
|
|
|
/* Sum up the pixel values. */
|
|
|
|
for (j = srcy; j < srcylimit; j++) {
|
|
// po points to the current pixel.
|
|
unsigned char *po = pos;
|
|
|
|
for (i = srcx; i < srcxlimit; i++) {
|
|
r += *po++;
|
|
g += *po++;
|
|
b += *po++;
|
|
a += *po++;
|
|
number += 1;
|
|
}
|
|
|
|
pos += srcpitch;
|
|
}
|
|
|
|
/* Compute the average pixel values. */
|
|
r /= number;
|
|
g /= number;
|
|
b /= number;
|
|
a /= number;
|
|
|
|
/* Write out the average pixel values. */
|
|
pos = &dstpixels[dsty * dstpitch + dstx * 4];
|
|
for (j = dsty; j < dstylimit; j++) {
|
|
unsigned char *po = pos;
|
|
|
|
for (i = dstx; i < dstxlimit; i++) {
|
|
*po++ = r;
|
|
*po++ = g;
|
|
*po++ = b;
|
|
*po++ = a;
|
|
}
|
|
|
|
pos += dstpitch;
|
|
}
|
|
}
|
|
}
|
|
|
|
Py_END_ALLOW_THREADS
|
|
|
|
}
|
|
|
|
/* This pixellates a 32-bit RGBA pygame surface to a destination
|
|
* surface of a given size.
|
|
*
|
|
* pysrc - The source pygame surface, which must be 32-bit RGBA.
|
|
* pydst - The destination pygame surface, which should be 32-bit
|
|
* RGBA, and locked.
|
|
* avgwidth - The width of the pixels that will be averaged together.
|
|
* avgheight - The height of the pixels that will be averaged
|
|
* together.
|
|
* outwidth - The width of pixels that will be written to the output.
|
|
* outheight - The height of pixels that will be written to the
|
|
* output.
|
|
*
|
|
* We assume that pysrc and pydst have been locked before we are called.
|
|
*/
|
|
void pixellate24_core(PyObject *pysrc,
|
|
PyObject *pydst,
|
|
int avgwidth,
|
|
int avgheight,
|
|
int outwidth,
|
|
int outheight
|
|
) {
|
|
|
|
SDL_Surface *src;
|
|
SDL_Surface *dst;
|
|
|
|
int x, y, i, j;
|
|
Uint32 srcpitch, dstpitch;
|
|
Uint32 srcw, srch;
|
|
Uint32 dstw, dsth;
|
|
int vw, vh;
|
|
|
|
unsigned char *srcpixels;
|
|
unsigned char *dstpixels;
|
|
|
|
src = PySurface_AsSurface(pysrc);
|
|
dst = PySurface_AsSurface(pydst);
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
|
|
srcpixels = (unsigned char *) src->pixels;
|
|
dstpixels = (unsigned char *) dst->pixels;
|
|
srcpitch = src->pitch;
|
|
dstpitch = dst->pitch;
|
|
srcw = src->w;
|
|
dstw = dst->w;
|
|
srch = src->h;
|
|
dsth = dst->h;
|
|
|
|
/* Compute the virtual width and height. */
|
|
vw = ( srcw + avgwidth - 1) / avgwidth;
|
|
vh = ( srch + avgheight - 1) / avgheight;
|
|
|
|
/* Iterate through each of the virtual pixels. */
|
|
|
|
for (y = 0; y < vh; y++) {
|
|
int srcy = avgheight * y;
|
|
int dsty = outheight * y;
|
|
|
|
int srcylimit = srcy + avgheight;
|
|
int dstylimit = dsty + outheight;
|
|
|
|
if (srcylimit > srch) {
|
|
srcylimit = srch;
|
|
}
|
|
|
|
if (dstylimit > dsth) {
|
|
dstylimit = dsth;
|
|
}
|
|
|
|
for (x = 0; x < vw; x++) {
|
|
int srcx = avgwidth * x;
|
|
int dstx = outwidth * x;
|
|
|
|
int srcxlimit = srcx + avgwidth;
|
|
int dstxlimit = dstx + outheight;
|
|
|
|
if (srcxlimit > srcw) {
|
|
srcxlimit = srcw;
|
|
}
|
|
|
|
if (dstxlimit > dstw) {
|
|
dstxlimit = dstw;
|
|
}
|
|
|
|
// Please note that these names are just
|
|
// suggestions... It's possible that blue will be
|
|
// in r, for example.
|
|
int r = 0;
|
|
int g = 0;
|
|
int b = 0;
|
|
|
|
int number = 0;
|
|
|
|
// pos always points to the start of the current line.
|
|
unsigned char *pos = &srcpixels[srcy * srcpitch + srcx * 3];
|
|
|
|
/* Sum up the pixel values. */
|
|
|
|
for (j = srcy; j < srcylimit; j++) {
|
|
// po points to the current pixel.
|
|
unsigned char *po = pos;
|
|
|
|
for (i = srcx; i < srcxlimit; i++) {
|
|
r += *po++;
|
|
g += *po++;
|
|
b += *po++;
|
|
number += 1;
|
|
}
|
|
|
|
pos += srcpitch;
|
|
}
|
|
|
|
/* Compute the average pixel values. */
|
|
r /= number;
|
|
g /= number;
|
|
b /= number;
|
|
|
|
/* Write out the average pixel values. */
|
|
pos = &dstpixels[dsty * dstpitch + dstx * 3];
|
|
for (j = dsty; j < dstylimit; j++) {
|
|
unsigned char *po = pos;
|
|
|
|
for (i = dstx; i < dstxlimit; i++) {
|
|
*po++ = r;
|
|
*po++ = g;
|
|
*po++ = b;
|
|
}
|
|
|
|
pos += dstpitch;
|
|
}
|
|
}
|
|
}
|
|
|
|
Py_END_ALLOW_THREADS
|
|
|
|
}
|
|
|
|
/*
|
|
* This expects pysrc and pydst to be surfaces of the same size. It
|
|
* the source surface to the destination surface, using the r, g, b,
|
|
* and a maps. These maps are expected to be 256 bytes long, with each
|
|
* byte corresponding to a possible value of a channel in pysrc,
|
|
* giving what that value is mapped to in pydst.
|
|
*/
|
|
void map32_core(PyObject *pysrc,
|
|
PyObject *pydst,
|
|
char *rmap,
|
|
char *gmap,
|
|
char *bmap,
|
|
char *amap) {
|
|
|
|
SDL_Surface *src;
|
|
SDL_Surface *dst;
|
|
|
|
int x, y;
|
|
Uint32 srcpitch, dstpitch;
|
|
Uint32 srcw, srch;
|
|
Uint32 dstw, dsth;
|
|
|
|
char *srcpixels;
|
|
char *dstpixels;
|
|
|
|
char *srcrow;
|
|
char *dstrow;
|
|
char *srcp;
|
|
char *dstp;
|
|
|
|
src = PySurface_AsSurface(pysrc);
|
|
dst = PySurface_AsSurface(pydst);
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
|
|
srcpixels = (char *) src->pixels;
|
|
dstpixels = (char *) dst->pixels;
|
|
srcpitch = src->pitch;
|
|
dstpitch = dst->pitch;
|
|
srcw = src->w;
|
|
dstw = dst->w;
|
|
srch = src->h;
|
|
dsth = dst->h;
|
|
|
|
srcrow = srcpixels;
|
|
dstrow = dstpixels;
|
|
|
|
for (y = 0; y < srch; y++) {
|
|
srcp = srcrow;
|
|
dstp = dstrow;
|
|
|
|
|
|
for (x = 0; x < srcw; x++) {
|
|
*dstp++ = rmap[(unsigned char) *srcp++];
|
|
*dstp++ = gmap[(unsigned char) *srcp++];
|
|
*dstp++ = bmap[(unsigned char) *srcp++];
|
|
*dstp++ = amap[(unsigned char) *srcp++];
|
|
}
|
|
|
|
srcrow += srcpitch;
|
|
dstrow += dstpitch;
|
|
}
|
|
|
|
Py_END_ALLOW_THREADS
|
|
}
|
|
|
|
void map24_core(PyObject *pysrc,
|
|
PyObject *pydst,
|
|
char *rmap,
|
|
char *gmap,
|
|
char *bmap) {
|
|
|
|
|
|
SDL_Surface *src;
|
|
SDL_Surface *dst;
|
|
|
|
int x, y;
|
|
Uint32 srcpitch, dstpitch;
|
|
Uint32 srcw, srch;
|
|
Uint32 dstw, dsth;
|
|
|
|
char *srcpixels;
|
|
char *dstpixels;
|
|
|
|
char *srcrow;
|
|
char *dstrow;
|
|
char *srcp;
|
|
char *dstp;
|
|
|
|
src = PySurface_AsSurface(pysrc);
|
|
dst = PySurface_AsSurface(pydst);
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
|
|
srcpixels = (char *) src->pixels;
|
|
dstpixels = (char *) dst->pixels;
|
|
srcpitch = src->pitch;
|
|
dstpitch = dst->pitch;
|
|
srcw = src->w;
|
|
dstw = dst->w;
|
|
srch = src->h;
|
|
dsth = dst->h;
|
|
|
|
srcrow = srcpixels;
|
|
dstrow = dstpixels;
|
|
|
|
for (y = 0; y < srch; y++) {
|
|
srcp = srcrow;
|
|
dstp = dstrow;
|
|
|
|
|
|
for (x = 0; x < srcw; x++) {
|
|
*dstp++ = rmap[(unsigned char) *srcp++];
|
|
*dstp++ = gmap[(unsigned char) *srcp++];
|
|
*dstp++ = bmap[(unsigned char) *srcp++];
|
|
}
|
|
|
|
srcrow += srcpitch;
|
|
dstrow += dstpitch;
|
|
}
|
|
|
|
Py_END_ALLOW_THREADS
|
|
}
|
|
|
|
/*
|
|
* This expects pysrc and pydst to be surfaces of the same size. It
|
|
* the source surface to the destination surface, using the r, g, b,
|
|
* and a maps. These maps are expected to be 256 bytes long, with each
|
|
* byte corresponding to a possible value of a channel in pysrc,
|
|
* giving what that value is mapped to in pydst.
|
|
*/
|
|
void linmap32_core(PyObject *pysrc,
|
|
PyObject *pydst,
|
|
int rmul,
|
|
int gmul,
|
|
int bmul,
|
|
int amul) {
|
|
|
|
SDL_Surface *src;
|
|
SDL_Surface *dst;
|
|
|
|
int x, y;
|
|
Uint32 srcpitch, dstpitch;
|
|
Uint32 srcw, srch;
|
|
Uint32 dstw, dsth;
|
|
|
|
char *srcpixels;
|
|
char *dstpixels;
|
|
|
|
char *srcrow;
|
|
char *dstrow;
|
|
char *srcp;
|
|
char *dstp;
|
|
|
|
src = PySurface_AsSurface(pysrc);
|
|
dst = PySurface_AsSurface(pydst);
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
|
|
srcpixels = (char *) src->pixels;
|
|
dstpixels = (char *) dst->pixels;
|
|
srcpitch = src->pitch;
|
|
dstpitch = dst->pitch;
|
|
srcw = src->w;
|
|
dstw = dst->w;
|
|
srch = src->h;
|
|
dsth = dst->h;
|
|
|
|
srcrow = srcpixels;
|
|
dstrow = dstpixels;
|
|
|
|
for (y = 0; y < srch; y++) {
|
|
srcp = srcrow;
|
|
dstp = dstrow;
|
|
|
|
|
|
for (x = 0; x < srcw; x++) {
|
|
*dstp++ = ((unsigned char) *srcp++) * rmul >> 8;
|
|
*dstp++ = ((unsigned char) *srcp++) * gmul >> 8;
|
|
*dstp++ = ((unsigned char) *srcp++) * bmul >> 8;
|
|
*dstp++ = ((unsigned char) *srcp++) * amul >> 8;
|
|
}
|
|
|
|
srcrow += srcpitch;
|
|
dstrow += dstpitch;
|
|
}
|
|
|
|
Py_END_ALLOW_THREADS
|
|
}
|
|
|
|
void linmap24_core(PyObject *pysrc,
|
|
PyObject *pydst,
|
|
int rmul,
|
|
int gmul,
|
|
int bmul) {
|
|
|
|
|
|
SDL_Surface *src;
|
|
SDL_Surface *dst;
|
|
|
|
int x, y;
|
|
Uint32 srcpitch, dstpitch;
|
|
Uint32 srcw, srch;
|
|
Uint32 dstw, dsth;
|
|
|
|
char *srcpixels;
|
|
char *dstpixels;
|
|
|
|
char *srcrow;
|
|
char *dstrow;
|
|
char *srcp;
|
|
char *dstp;
|
|
|
|
src = PySurface_AsSurface(pysrc);
|
|
dst = PySurface_AsSurface(pydst);
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
|
|
srcpixels = (char *) src->pixels;
|
|
dstpixels = (char *) dst->pixels;
|
|
srcpitch = src->pitch;
|
|
dstpitch = dst->pitch;
|
|
srcw = src->w;
|
|
dstw = dst->w;
|
|
srch = src->h;
|
|
dsth = dst->h;
|
|
|
|
srcrow = srcpixels;
|
|
dstrow = dstpixels;
|
|
|
|
for (y = 0; y < srch; y++) {
|
|
srcp = srcrow;
|
|
dstp = dstrow;
|
|
|
|
|
|
for (x = 0; x < srcw; x++) {
|
|
*dstp++ = ((unsigned char) *srcp++) * rmul >> 8;
|
|
*dstp++ = ((unsigned char) *srcp++) * gmul >> 8;
|
|
*dstp++ = ((unsigned char) *srcp++) * bmul >> 8;
|
|
}
|
|
|
|
srcrow += srcpitch;
|
|
dstrow += dstpitch;
|
|
}
|
|
|
|
Py_END_ALLOW_THREADS
|
|
}
|
|
|
|
|
|
#if 0
|
|
|
|
void xblur32_core(PyObject *pysrc,
|
|
PyObject *pydst,
|
|
int radius) {
|
|
|
|
int i, x, y;
|
|
|
|
SDL_Surface *src;
|
|
SDL_Surface *dst;
|
|
|
|
Uint32 srcpitch, dstpitch;
|
|
Uint32 srcw, srch;
|
|
Uint32 dstw, dsth;
|
|
|
|
unsigned char *srcpixels;
|
|
unsigned char *dstpixels;
|
|
|
|
int count;
|
|
|
|
unsigned char *srcp;
|
|
unsigned char *dstp;
|
|
|
|
|
|
src = PySurface_AsSurface(pysrc);
|
|
dst = PySurface_AsSurface(pydst);
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
|
|
srcpixels = (unsigned char *) src->pixels;
|
|
dstpixels = (unsigned char *) dst->pixels;
|
|
srcpitch = src->pitch;
|
|
dstpitch = dst->pitch;
|
|
srcw = src->w;
|
|
dstw = dst->w;
|
|
srch = src->h;
|
|
dsth = dst->h;
|
|
|
|
int divisor = radius * 2 + 1;
|
|
|
|
for (y = 0; y < dsth; y++) {
|
|
|
|
// The values of the pixels on the left and right ends of the
|
|
// line.
|
|
unsigned char lr, lg, lb, la;
|
|
unsigned char rr, rg, rb, ra;
|
|
|
|
unsigned char *leader = srcpixels + y * srcpitch;
|
|
unsigned char *trailer = leader;
|
|
dstp = dstpixels + y * dstpitch;
|
|
|
|
lr = *leader;
|
|
lg = *(leader + 1);
|
|
lb = *(leader + 2);
|
|
la = *(leader + 3);
|
|
|
|
int sumr = lr * radius;
|
|
int sumg = lg * radius;
|
|
int sumb = lb * radius;
|
|
int suma = la * radius;
|
|
|
|
|
|
for (x = 0; x < radius + 0; x++) {
|
|
sumr += *leader++;
|
|
sumg += *leader++;
|
|
sumb += *leader++;
|
|
suma += *leader++;
|
|
}
|
|
|
|
// left side of the kernel is off of the screen.
|
|
for (x = 0; x < radius; x++) {
|
|
sumr += *leader++;
|
|
sumg += *leader++;
|
|
sumb += *leader++;
|
|
suma += *leader++;
|
|
|
|
*dstp++ = sumr / divisor;
|
|
*dstp++ = sumg / divisor;
|
|
*dstp++ = sumb / divisor;
|
|
*dstp++ = suma / divisor;
|
|
|
|
sumr -= lr;
|
|
sumg -= lg;
|
|
sumb -= lb;
|
|
suma -= la;
|
|
}
|
|
|
|
int end = srcw - radius - 1;
|
|
|
|
// The kernel is fully on the screen.
|
|
for (; x < end; x++) {
|
|
sumr += *leader++;
|
|
sumg += *leader++;
|
|
sumb += *leader++;
|
|
suma += *leader++;
|
|
|
|
*dstp++ = sumr / divisor;
|
|
*dstp++ = sumg / divisor;
|
|
*dstp++ = sumb / divisor;
|
|
*dstp++ = suma / divisor;
|
|
|
|
sumr -= *trailer++;
|
|
sumg -= *trailer++;
|
|
sumb -= *trailer++;
|
|
suma -= *trailer++;
|
|
}
|
|
|
|
rr = *leader++;
|
|
rg = *leader++;
|
|
rb = *leader++;
|
|
ra = *leader++;
|
|
|
|
// The kernel is off the right side of the screen.
|
|
for (; x < srcw; x++) {
|
|
sumr += rr;
|
|
sumg += rg;
|
|
sumb += rb;
|
|
suma += ra;
|
|
|
|
*dstp++ = sumr / divisor;
|
|
*dstp++ = sumg / divisor;
|
|
*dstp++ = sumb / divisor;
|
|
*dstp++ = suma / divisor;
|
|
|
|
sumr -= *trailer++;
|
|
sumg -= *trailer++;
|
|
sumb -= *trailer++;
|
|
suma -= *trailer++;
|
|
}
|
|
}
|
|
|
|
Py_END_ALLOW_THREADS
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
// Alpha Munge takes a channel from the source pixel, maps it, and
|
|
// sticks it into the alpha channel of the destination, overwriting
|
|
// the destination's alpha channel.
|
|
//
|
|
// It's used to implement SmartDissolve.
|
|
|
|
void alphamunge_core(PyObject *pysrc,
|
|
PyObject *pydst,
|
|
int src_bypp, // bytes per pixel.
|
|
int src_aoff, // alpha offset.
|
|
int dst_aoff, // alpha offset.
|
|
char *amap) {
|
|
|
|
int x, y;
|
|
|
|
SDL_Surface *src;
|
|
SDL_Surface *dst;
|
|
|
|
Uint32 srcpitch, dstpitch;
|
|
Uint32 srcw, srch;
|
|
Uint32 dstw, dsth;
|
|
|
|
unsigned char *srcpixels;
|
|
unsigned char *dstpixels;
|
|
|
|
unsigned char *srcline;
|
|
unsigned char *dstline;
|
|
|
|
unsigned char *srcp;
|
|
unsigned char *dstp;
|
|
|
|
|
|
src = PySurface_AsSurface(pysrc);
|
|
dst = PySurface_AsSurface(pydst);
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
|
|
srcpixels = (unsigned char *) src->pixels;
|
|
dstpixels = (unsigned char *) dst->pixels;
|
|
srcpitch = src->pitch;
|
|
dstpitch = dst->pitch;
|
|
srcw = src->w;
|
|
dstw = dst->w;
|
|
srch = src->h;
|
|
dsth = dst->h;
|
|
|
|
|
|
// We assume that src is bigger than dst, and so use dst
|
|
// to handle everything.
|
|
|
|
srcline = srcpixels;
|
|
dstline = dstpixels;
|
|
|
|
for (y = 0; y < dsth; y++) {
|
|
|
|
srcp = srcline + src_aoff;
|
|
dstp = dstline + dst_aoff;
|
|
|
|
for (x = 0; x < dstw; x++) {
|
|
|
|
*dstp = amap[*srcp];
|
|
srcp += src_bypp;
|
|
dstp += 4; // Need an alpha channel.
|
|
}
|
|
|
|
srcline += srcpitch;
|
|
dstline += dstpitch;
|
|
|
|
}
|
|
|
|
Py_END_ALLOW_THREADS
|
|
}
|
|
|
|
void scale32_core(PyObject *pysrc, PyObject *pydst,
|
|
float source_xoff, float source_yoff,
|
|
float source_width, float source_height,
|
|
float dest_xoff, float dest_yoff,
|
|
float dest_width, float dest_height) {
|
|
|
|
|
|
SDL_Surface *src;
|
|
SDL_Surface *dst;
|
|
|
|
int y;
|
|
Uint32 srcpitch, dstpitch;
|
|
Uint32 srcw, srch;
|
|
Uint32 dstw, dsth;
|
|
float xdelta, ydelta;
|
|
|
|
unsigned char *srcpixels;
|
|
unsigned char *dstpixels;
|
|
|
|
|
|
src = PySurface_AsSurface(pysrc);
|
|
dst = PySurface_AsSurface(pydst);
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
|
|
srcpixels = (unsigned char *) src->pixels;
|
|
dstpixels = (unsigned char *) dst->pixels;
|
|
srcpitch = src->pitch;
|
|
dstpitch = dst->pitch;
|
|
srcw = src->w;
|
|
dstw = dst->w;
|
|
srch = src->h;
|
|
dsth = dst->h;
|
|
|
|
xdelta = 255.0 * (source_width - 1) / dest_width;
|
|
ydelta = 255.0 * (source_height - 1) / dest_height;
|
|
|
|
for (y = 0; y < dsth; y++) {
|
|
|
|
unsigned char *s0;
|
|
unsigned char *s1;
|
|
unsigned char *d;
|
|
unsigned char *dend;
|
|
|
|
int sline;
|
|
short s0frac;
|
|
short s1frac;
|
|
float scol;
|
|
|
|
d = dstpixels + dstpitch * y;
|
|
dend = d + 4 * dstw; // bpp
|
|
|
|
sline = source_yoff * 255 + (y + dest_yoff) * ydelta;
|
|
s1frac = (int) sline & 255;
|
|
s0frac = 256 - s1frac;
|
|
|
|
s0 = srcpixels + (sline >> 8) * srcpitch;
|
|
s1 = s0 + srcpitch;
|
|
|
|
scol = source_xoff * 255 + dest_xoff * xdelta;
|
|
|
|
while (d < dend) {
|
|
|
|
unsigned char *s0p;
|
|
unsigned char *s1p;
|
|
|
|
short xfrac = 256 - ((int) scol & 255);
|
|
unsigned short r, g, b, a;
|
|
|
|
s0p = s0 + ((int) scol >> 8) * 4; // bpp
|
|
s1p = s0p + srcpitch;
|
|
|
|
r = (((*s0p++ * s0frac) + (*s1p++ * s1frac)) >> 8) * xfrac;
|
|
g = (((*s0p++ * s0frac) + (*s1p++ * s1frac)) >> 8) * xfrac;
|
|
b = (((*s0p++ * s0frac) + (*s1p++ * s1frac)) >> 8) * xfrac;
|
|
a = (((*s0p++ * s0frac) + (*s1p++ * s1frac)) >> 8) * xfrac;
|
|
|
|
xfrac = 256 - xfrac;
|
|
|
|
r += (((*s0p++ * s0frac) + (*s1p++ * s1frac)) >> 8) * xfrac;
|
|
g += (((*s0p++ * s0frac) + (*s1p++ * s1frac)) >> 8) * xfrac;
|
|
b += (((*s0p++ * s0frac) + (*s1p++ * s1frac)) >> 8) * xfrac;
|
|
a += (((*s0p++ * s0frac) + (*s1p++ * s1frac)) >> 8) * xfrac;
|
|
|
|
*d++ = r >> 8;
|
|
*d++ = g >> 8;
|
|
*d++ = b >> 8;
|
|
*d++ = a >> 8;
|
|
|
|
scol += xdelta;
|
|
}
|
|
}
|
|
|
|
Py_END_ALLOW_THREADS
|
|
}
|
|
|
|
|
|
void scale24_core(PyObject *pysrc, PyObject *pydst,
|
|
float source_xoff, float source_yoff,
|
|
float source_width, float source_height,
|
|
float dest_xoff, float dest_yoff,
|
|
float dest_width, float dest_height) {
|
|
|
|
|
|
SDL_Surface *src;
|
|
SDL_Surface *dst;
|
|
|
|
int y;
|
|
Uint32 srcpitch, dstpitch;
|
|
Uint32 srcw, srch;
|
|
Uint32 dstw, dsth;
|
|
float xdelta, ydelta;
|
|
|
|
unsigned char *srcpixels;
|
|
unsigned char *dstpixels;
|
|
|
|
|
|
src = PySurface_AsSurface(pysrc);
|
|
dst = PySurface_AsSurface(pydst);
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
|
|
srcpixels = (unsigned char *) src->pixels;
|
|
dstpixels = (unsigned char *) dst->pixels;
|
|
srcpitch = src->pitch;
|
|
dstpitch = dst->pitch;
|
|
srcw = src->w;
|
|
dstw = dst->w;
|
|
srch = src->h;
|
|
dsth = dst->h;
|
|
|
|
xdelta = 255.0 * (source_width - 1) / dest_width;
|
|
ydelta = 255.0 * (source_height - 1) / dest_height;
|
|
|
|
for (y = 0; y < dsth; y++) {
|
|
|
|
unsigned char *s0;
|
|
unsigned char *s1;
|
|
unsigned char *d;
|
|
unsigned char *dend;
|
|
|
|
int sline;
|
|
short s0frac;
|
|
short s1frac;
|
|
float scol;
|
|
|
|
d = dstpixels + dstpitch * y;
|
|
dend = d + 3 * dstw; // bpp
|
|
|
|
sline = source_yoff * 255 + (y + dest_yoff) * ydelta;
|
|
s1frac = (int) sline & 255;
|
|
s0frac = 256 - s1frac;
|
|
|
|
s0 = srcpixels + (sline >> 8) * srcpitch;
|
|
s1 = s0 + srcpitch;
|
|
|
|
scol = source_xoff * 255 + dest_xoff * xdelta;
|
|
|
|
while (d < dend) {
|
|
|
|
unsigned char *s0p;
|
|
unsigned char *s1p;
|
|
|
|
short xfrac = 256 - ((int) scol & 255);
|
|
unsigned short r, g, b;
|
|
|
|
s0p = s0 + ((int) scol >> 8) * 3; // bpp
|
|
s1p = s0p + srcpitch;
|
|
|
|
r = (((*s0p++ * s0frac) + (*s1p++ * s1frac)) >> 8) * xfrac;
|
|
g = (((*s0p++ * s0frac) + (*s1p++ * s1frac)) >> 8) * xfrac;
|
|
b = (((*s0p++ * s0frac) + (*s1p++ * s1frac)) >> 8) * xfrac;
|
|
|
|
xfrac = 256 - xfrac;
|
|
|
|
r += (((*s0p++ * s0frac) + (*s1p++ * s1frac)) >> 8) * xfrac;
|
|
g += (((*s0p++ * s0frac) + (*s1p++ * s1frac)) >> 8) * xfrac;
|
|
b += (((*s0p++ * s0frac) + (*s1p++ * s1frac)) >> 8) * xfrac;
|
|
|
|
*d++ = r >> 8;
|
|
*d++ = g >> 8;
|
|
*d++ = b >> 8;
|
|
|
|
scol += xdelta;
|
|
}
|
|
}
|
|
|
|
Py_END_ALLOW_THREADS
|
|
}
|
|
|
|
#define I(a, b, mul) ((((((b - a) * mul)) >> 8) + a) & 0xff00ff)
|
|
|
|
/****************************************************************************/
|
|
/* A similar concept to rotozoom, but implemented differently, so we
|
|
can limit the target area. */
|
|
void transform32_std(PyObject *pysrc, PyObject *pydst,
|
|
float corner_x, float corner_y,
|
|
float xdx, float ydx,
|
|
float xdy, float ydy,
|
|
int ashift, float a) {
|
|
|
|
SDL_Surface *src;
|
|
SDL_Surface *dst;
|
|
|
|
int y;
|
|
int srcpitch, dstpitch;
|
|
int srcw, srch;
|
|
int dstw, dsth;
|
|
|
|
unsigned char *srcpixels;
|
|
unsigned char *dstpixels;
|
|
|
|
float lsx, lsy; // The position of the current line in the source.
|
|
float sx, sy; // The position of the current pixel in the source.
|
|
|
|
src = PySurface_AsSurface(pysrc);
|
|
dst = PySurface_AsSurface(pydst);
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
|
|
srcpixels = (unsigned char *) src->pixels;
|
|
dstpixels = (unsigned char *) dst->pixels;
|
|
srcpitch = src->pitch;
|
|
dstpitch = dst->pitch;
|
|
srcw = src->w;
|
|
dstw = dst->w;
|
|
srch = src->h;
|
|
dsth = dst->h;
|
|
|
|
unsigned int amul = (int) (a * 256);
|
|
|
|
lsx = corner_x * 256;
|
|
lsy = corner_y * 256;
|
|
|
|
xdx *= 256;
|
|
ydx *= 256;
|
|
xdy *= 256;
|
|
ydy *= 256;
|
|
|
|
|
|
// Scaled subtracted srcw and srch.
|
|
float fsw = (srcw - 1) * 256;
|
|
float fsh = (srch - 1) * 256;
|
|
|
|
for (y = 0; y < dsth; y++, lsx += xdy, lsy += ydy) {
|
|
|
|
sx = lsx;
|
|
sy = lsy;
|
|
|
|
// unsigned char *d = dstpixels + dstpitch * y;
|
|
// unsigned char *dend = d + 4 * dstw;
|
|
|
|
float minx = 0;
|
|
float maxx = dstw - 1;
|
|
|
|
if (xdx != 0) {
|
|
float d1 = -lsx / xdx;
|
|
float d2 = (fsw - lsx) / xdx;
|
|
|
|
minx = fmaxf(minx, fminf(d1, d2));
|
|
maxx = fminf(maxx, fmaxf(d1, d2));
|
|
|
|
// printf("ZZZ1 %f %f\n", d1, d2);
|
|
} else if ( lsx < 0 || lsx >= fsw) {
|
|
continue;
|
|
}
|
|
|
|
if (ydx != 0) {
|
|
float d1 = -lsy / ydx;
|
|
float d2 = (fsh - lsy) / ydx;
|
|
|
|
minx = fmaxf(minx, fminf(d1, d2));
|
|
maxx = fminf(maxx, fmaxf(d1, d2));
|
|
} else if ( lsy < 0 || lsy >= fsh) {
|
|
continue;
|
|
}
|
|
|
|
if (minx > maxx) {
|
|
continue;
|
|
}
|
|
|
|
minx = ceil(minx);
|
|
maxx = floor(maxx);
|
|
|
|
unsigned char *d = dstpixels + dstpitch * y;
|
|
unsigned char *dend = d + 4 * (int) maxx;
|
|
d += 4 * (int) minx;
|
|
|
|
sx = lsx + minx * xdx;
|
|
sy = lsy + minx * ydx;
|
|
|
|
int sxi = (int) sx;
|
|
int syi = (int) sy;
|
|
int xdxi = (int) xdx;
|
|
int ydxi = (int) ydx;
|
|
|
|
while (d <= dend) {
|
|
int px, py;
|
|
px = sxi >> 8;
|
|
py = syi >> 8;
|
|
|
|
unsigned char *sp = srcpixels + py * srcpitch + px * 4;
|
|
|
|
int yfrac = syi & 0xff; // ((short) sy) & 0xff;
|
|
int xfrac = sxi & 0xff; // ((short) sx) & 0xff;
|
|
|
|
unsigned int pal = *(unsigned int *) sp;
|
|
unsigned int pbl = *(unsigned int *) (sp + 4);
|
|
sp += srcpitch;
|
|
unsigned int pcl = *(unsigned int *) sp;
|
|
unsigned int pdl = *(unsigned int *) (sp + 4);
|
|
|
|
unsigned int pah = (pal >> 8) & 0xff00ff;
|
|
unsigned int pbh = (pbl >> 8) & 0xff00ff;
|
|
unsigned int pch = (pcl >> 8) & 0xff00ff;
|
|
unsigned int pdh = (pdl >> 8) & 0xff00ff;
|
|
|
|
pal &= 0xff00ff;
|
|
pbl &= 0xff00ff;
|
|
pcl &= 0xff00ff;
|
|
pdl &= 0xff00ff;
|
|
|
|
unsigned int rh = I(I(pah, pch, yfrac), I(pbh, pdh, yfrac), xfrac);
|
|
unsigned int rl = I(I(pal, pcl, yfrac), I(pbl, pdl, yfrac), xfrac);
|
|
|
|
unsigned int alpha = (((rh << 8) | rl) >> ashift) & 0xff;
|
|
alpha = (alpha * amul) >> 8;
|
|
|
|
unsigned int dl = * (unsigned int *) d;
|
|
unsigned int dh = (dl >> 8) & 0xff00ff;
|
|
dl &= 0xff00ff;
|
|
|
|
dl = I(dl, rl, alpha);
|
|
dh = I(dh, rh, alpha);
|
|
|
|
* (unsigned int *) d = (dh << 8) | dl;
|
|
|
|
d += 4;
|
|
sxi += xdxi;
|
|
syi += ydxi;
|
|
}
|
|
}
|
|
|
|
Py_END_ALLOW_THREADS
|
|
}
|
|
|
|
#ifdef GCC_MMX
|
|
|
|
/****************************************************************************/
|
|
/* A similar concept to rotozoom, but implemented differently, so we
|
|
can limit the target area. */
|
|
void transform32_mmx(PyObject *pysrc, PyObject *pydst,
|
|
float corner_x, float corner_y,
|
|
float xdx, float ydx,
|
|
float xdy, float ydy,
|
|
int ashift,
|
|
float a) {
|
|
|
|
SDL_Surface *src;
|
|
SDL_Surface *dst;
|
|
|
|
int y;
|
|
int srcpitch, dstpitch;
|
|
|
|
int srcw, srch;
|
|
int dstw, dsth;
|
|
|
|
unsigned char *srcpixels;
|
|
unsigned char *dstpixels;
|
|
|
|
float lsx, lsy; // The position of the current line in the source.
|
|
float sx, sy; // The position of the current pixel in the source.
|
|
|
|
src = PySurface_AsSurface(pysrc);
|
|
dst = PySurface_AsSurface(pydst);
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
|
|
srcpixels = (unsigned char *) src->pixels;
|
|
dstpixels = (unsigned char *) dst->pixels;
|
|
srcpitch = src->pitch;
|
|
dstpitch = dst->pitch;
|
|
srcw = src->w;
|
|
dstw = dst->w;
|
|
srch = src->h;
|
|
dsth = dst->h;
|
|
|
|
// Due to mmx.
|
|
ashift *= 2;
|
|
|
|
// Compute the coloring multiplier.
|
|
unsigned int amul = (unsigned int) (a * 256);
|
|
|
|
lsx = corner_x * 256;
|
|
lsy = corner_y * 256;
|
|
|
|
xdx *= 256;
|
|
ydx *= 256;
|
|
xdy *= 256;
|
|
ydy *= 256;
|
|
|
|
// Scaled subtracted srcw and srch.
|
|
float fsw = (srcw - 2) * 256;
|
|
float fsh = (srch - 2) * 256;
|
|
|
|
for (y = 0; y < dsth; y++, lsx += xdy, lsy += ydy) {
|
|
|
|
float minx = 0;
|
|
float maxx = dstw - 1;
|
|
|
|
if (xdx != 0) {
|
|
float d1 = -lsx / xdx;
|
|
float d2 = (fsw - lsx) / xdx;
|
|
|
|
minx = fmaxf(minx, fminf(d1, d2));
|
|
maxx = fminf(maxx, fmaxf(d1, d2));
|
|
|
|
} else if ( lsx < 0 || lsx >= fsw) {
|
|
continue;
|
|
}
|
|
|
|
if (ydx != 0) {
|
|
float d1 = -lsy / ydx;
|
|
float d2 = (fsh - lsy) / ydx;
|
|
|
|
minx = fmaxf(minx, fminf(d1, d2));
|
|
maxx = fminf(maxx, fmaxf(d1, d2));
|
|
} else if ( lsy < 0 || lsy >= fsh) {
|
|
continue;
|
|
}
|
|
|
|
if (minx > maxx) {
|
|
continue;
|
|
}
|
|
|
|
minx = ceil(minx);
|
|
maxx = floor(maxx);
|
|
|
|
unsigned char *d = dstpixels + dstpitch * y;
|
|
unsigned char *dend = d + 4 * (int) maxx;
|
|
d += 4 * (int) minx;
|
|
|
|
sx = lsx + minx * xdx;
|
|
sy = lsy + minx * ydx;
|
|
|
|
// No floating point allowed between here and the end of the
|
|
// while loop.
|
|
|
|
int sxi = (int) sx;
|
|
int syi = (int) sy;
|
|
int xdxi = (int) xdx;
|
|
int ydxi = (int) ydx;
|
|
|
|
// 0 -> mm7
|
|
pxor_r2r(mm7, mm7);
|
|
|
|
// ashift -> mm0
|
|
movd_m2r(ashift, mm0);
|
|
|
|
// amul -> mm4
|
|
movd_m2r(amul, mm4);
|
|
|
|
while (d <= dend) {
|
|
|
|
int px, py;
|
|
px = sxi >> 8;
|
|
py = syi >> 8;
|
|
|
|
unsigned char *sp = srcpixels + py * srcpitch + px * 4;
|
|
|
|
int yfrac = syi & 0xff; // ((short) sy) & 0xff;
|
|
int xfrac = sxi & 0xff; // ((short) sx) & 0xff;
|
|
|
|
// Put xfrac in mm5, yfrac in m6
|
|
pxor_r2r(mm5, mm5);
|
|
pxor_r2r(mm6, mm6);
|
|
movd_m2r(xfrac, mm5);
|
|
movd_m2r(yfrac, mm6);
|
|
punpcklwd_r2r(mm5, mm5);
|
|
punpcklwd_r2r(mm6, mm6);
|
|
punpckldq_r2r(mm5, mm5); /* 0X0X0X0X -> mm5 */
|
|
punpckldq_r2r(mm6, mm6); /* 0Y0Y0Y0Y -> mm6 */
|
|
|
|
// Load in the 4 bytes.
|
|
movd_m2r(*(unsigned int *) sp, mm1);
|
|
movd_m2r(*(unsigned int *) (sp + 4), mm2);
|
|
punpcklbw_r2r(mm7, mm1);
|
|
punpcklbw_r2r(mm7, mm2);
|
|
|
|
// Interpolate between a and b.
|
|
psubw_r2r(mm1, mm2);
|
|
pmullw_r2r(mm5, mm2);
|
|
psrlw_i2r(8, mm2);
|
|
paddb_r2r(mm2, mm1); /* mm1 contains I(a, b, xfrac); */
|
|
|
|
sp += srcpitch;
|
|
movd_m2r(*(unsigned int *) sp, mm3);
|
|
movd_m2r(*(unsigned int *) (sp + 4), mm2);
|
|
|
|
punpcklbw_r2r(mm7, mm3);
|
|
punpcklbw_r2r(mm7, mm2);
|
|
|
|
// Interpolate between c and d.
|
|
psubw_r2r(mm3, mm2);
|
|
pmullw_r2r(mm5, mm2);
|
|
psrlw_i2r(8, mm2);
|
|
paddb_r2r(mm2, mm3); /* mm3 contains I(c, d, xfrac); */
|
|
|
|
// Interpolate between ab and cd.
|
|
psubw_r2r(mm1, mm3);
|
|
pmullw_r2r(mm6, mm3);
|
|
psrlw_i2r(8, mm3);
|
|
paddb_r2r(mm3, mm1); /* mm1 contains I(ab, cd, yfrac) */
|
|
|
|
|
|
// Store the result.
|
|
// packuswb_r2r(mm7, mm1);
|
|
// movd_r2m(mm1, *(unsigned int *)d);
|
|
|
|
// Alpha blend with dest.
|
|
movq_r2r(mm1, mm3);
|
|
psrlq_r2r(mm0, mm3); /* 000000AA -> m3 */
|
|
|
|
pmullw_r2r(mm4, mm3); // Alpha adjustment.
|
|
psrlw_i2r(8, mm3);
|
|
|
|
punpcklwd_r2r(mm3, mm3); /* 0000AAAA -> m3 */
|
|
movd_m2r(*(unsigned int *)d, mm2);
|
|
punpcklwd_r2r(mm3, mm3); /* AAAAAAAA -> m3 */
|
|
punpcklbw_r2r(mm7, mm2); /* a -> m2 */
|
|
psubw_r2r(mm2, mm1); /* b - a -> m1 */
|
|
pmullw_r2r(mm3, mm1);
|
|
psrlw_i2r(8, mm1); /* alpha * (b-a) -> m1 */
|
|
paddb_r2r(mm2, mm1); /* a + alpha*(b-a) -> mm1 */
|
|
|
|
// Store the result.
|
|
packuswb_r2r(mm7, mm1);
|
|
movd_r2m(mm1, *(unsigned int *)d);
|
|
|
|
d += 4;
|
|
sxi += xdxi;
|
|
syi += ydxi;
|
|
}
|
|
|
|
emms();
|
|
|
|
}
|
|
|
|
Py_END_ALLOW_THREADS
|
|
}
|
|
|
|
#endif
|
|
|
|
void transform32_core(PyObject *pysrc, PyObject *pydst,
|
|
float corner_x, float corner_y,
|
|
float xdx, float ydx,
|
|
float xdy, float ydy,
|
|
int ashift,
|
|
float a) {
|
|
|
|
#ifdef GCC_MMX
|
|
static int checked_mmx = 0;
|
|
static int has_mmx = 0;
|
|
|
|
if (! checked_mmx) {
|
|
has_mmx = SDL_HasMMX();
|
|
checked_mmx = 1;
|
|
}
|
|
|
|
if (has_mmx) {
|
|
transform32_mmx(pysrc, pydst, corner_x, corner_y,
|
|
xdx, ydx, xdy, ydy, ashift, a);
|
|
return;
|
|
}
|
|
|
|
#endif
|
|
|
|
transform32_std(pysrc, pydst, corner_x, corner_y,
|
|
xdx, ydx, xdy, ydy, ashift, a);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void blend32_core_std(PyObject *pysrca, PyObject *pysrcb, PyObject *pydst,
|
|
int alpha) {
|
|
|
|
SDL_Surface *srca;
|
|
SDL_Surface *srcb;
|
|
SDL_Surface *dst;
|
|
|
|
int srcapitch, srcbpitch, dstpitch;
|
|
unsigned short dstw, dsth;
|
|
unsigned short y;
|
|
|
|
unsigned char *srcapixels;
|
|
unsigned char *srcbpixels;
|
|
unsigned char *dstpixels;
|
|
|
|
srca = PySurface_AsSurface(pysrca);
|
|
srcb = PySurface_AsSurface(pysrcb);
|
|
dst = PySurface_AsSurface(pydst);
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
|
|
srcapixels = (unsigned char *) srca->pixels;
|
|
srcbpixels = (unsigned char *) srcb->pixels;
|
|
dstpixels = (unsigned char *) dst->pixels;
|
|
srcapitch = srca->pitch;
|
|
srcbpitch = srcb->pitch;
|
|
dstpitch = dst->pitch;
|
|
dstw = dst->w;
|
|
dsth = dst->h;
|
|
|
|
for (y = 0; y < dsth; y++) {
|
|
|
|
unsigned int *dp = (unsigned int *)(dstpixels + dstpitch * y);
|
|
unsigned int *dpe = dp + dstw;
|
|
|
|
unsigned int *sap = (unsigned int *)(srcapixels + srcapitch * y);
|
|
unsigned int *sbp = (unsigned int *)(srcbpixels + srcbpitch * y);
|
|
|
|
while (dp < dpe) {
|
|
unsigned int sal = *sap++;
|
|
unsigned int sbl = *sbp++;
|
|
|
|
unsigned int sah = (sal >> 8) & 0xff00ff;
|
|
unsigned int sbh = (sbl >> 8) & 0xff00ff;
|
|
|
|
sal &= 0xff00ff;
|
|
sbl &= 0xff00ff;
|
|
|
|
*dp++ = I(sal, sbl, alpha) | (I(sah, sbh, alpha) << 8);
|
|
}
|
|
}
|
|
|
|
Py_END_ALLOW_THREADS
|
|
|
|
}
|
|
|
|
#ifdef GCC_MMX
|
|
|
|
void blend32_core_mmx(PyObject *pysrca, PyObject *pysrcb, PyObject *pydst,
|
|
int alpha) {
|
|
|
|
SDL_Surface *srca;
|
|
SDL_Surface *srcb;
|
|
SDL_Surface *dst;
|
|
|
|
int srcapitch, srcbpitch, dstpitch;
|
|
unsigned short dstw, dsth;
|
|
unsigned short y;
|
|
|
|
unsigned char *srcapixels;
|
|
unsigned char *srcbpixels;
|
|
unsigned char *dstpixels;
|
|
|
|
srca = PySurface_AsSurface(pysrca);
|
|
srcb = PySurface_AsSurface(pysrcb);
|
|
dst = PySurface_AsSurface(pydst);
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
|
|
srcapixels = (unsigned char *) srca->pixels;
|
|
srcbpixels = (unsigned char *) srcb->pixels;
|
|
dstpixels = (unsigned char *) dst->pixels;
|
|
srcapitch = srca->pitch;
|
|
srcbpitch = srcb->pitch;
|
|
dstpitch = dst->pitch;
|
|
dstw = dst->w;
|
|
dsth = dst->h;
|
|
|
|
/* This code is a slightly modified version of that found in
|
|
* SDL_blit_A.c */
|
|
|
|
pxor_r2r(mm5, mm5); /* 0 -> mm5 */
|
|
/* form the alpha mult */
|
|
movd_m2r(alpha, mm4); /* 0000000A -> mm4 */
|
|
punpcklwd_r2r(mm4, mm4); /* 00000A0A -> mm4 */
|
|
punpckldq_r2r(mm4, mm4); /* 0A0A0A0A -> mm4 */
|
|
|
|
for (y = 0; y < dsth; y++) {
|
|
|
|
unsigned int *dp = (unsigned int *)(dstpixels + dstpitch * y);
|
|
unsigned int *dpe = dp + dstw;
|
|
|
|
unsigned int *sap = (unsigned int *)(srcapixels + srcapitch * y);
|
|
unsigned int *sbp = (unsigned int *)(srcbpixels + srcbpitch * y);
|
|
|
|
while (dp < dpe) {
|
|
|
|
movd_m2r((*sbp++), mm1);
|
|
movd_m2r((*sap++), mm2);
|
|
punpcklbw_r2r(mm5, mm1); /* 0A0R0G0B -> mm1(b) */
|
|
punpcklbw_r2r(mm5, mm2); /* 0A0R0G0B -> mm2(a) */
|
|
psubw_r2r(mm2, mm1);/* a - b -> mm1 */
|
|
pmullw_r2r(mm4, mm1); /* mm1 * alpha -> mm1 */
|
|
psrlw_i2r(8, mm1); /* mm1 >> 8 -> mm1 */
|
|
paddb_r2r(mm1, mm2); /* mm1 + mm2(a) -> mm2 */
|
|
packuswb_r2r(mm5, mm2); /* ARGBARGB -> mm2 */
|
|
movd_r2m(mm2, *dp++);
|
|
|
|
|
|
}
|
|
}
|
|
|
|
emms();
|
|
Py_END_ALLOW_THREADS
|
|
}
|
|
|
|
#endif
|
|
|
|
void blend32_core(PyObject *pysrca, PyObject *pysrcb, PyObject *pydst,
|
|
int alpha) {
|
|
|
|
#ifdef GCC_MMX
|
|
static int checked_mmx = 0;
|
|
static int has_mmx = 0;
|
|
|
|
if (! checked_mmx) {
|
|
has_mmx = SDL_HasMMX();
|
|
checked_mmx = 1;
|
|
}
|
|
|
|
if (has_mmx) {
|
|
blend32_core_mmx(pysrca, pysrcb, pydst, alpha);
|
|
return;
|
|
}
|
|
|
|
#endif
|
|
|
|
blend32_core_std(pysrca, pysrcb, pydst, alpha);
|
|
}
|
|
|
|
|
|
void imageblend32_core_std(PyObject *pysrca, PyObject *pysrcb,
|
|
PyObject *pydst, PyObject *pyimg,
|
|
int alpha_off, char *amap) {
|
|
|
|
SDL_Surface *srca;
|
|
SDL_Surface *srcb;
|
|
SDL_Surface *dst;
|
|
SDL_Surface *img;
|
|
|
|
int srcapitch, srcbpitch, dstpitch, imgpitch;
|
|
unsigned short dstw, dsth;
|
|
unsigned short y;
|
|
|
|
unsigned char *srcapixels;
|
|
unsigned char *srcbpixels;
|
|
unsigned char *dstpixels;
|
|
unsigned char *imgpixels;
|
|
|
|
srca = PySurface_AsSurface(pysrca);
|
|
srcb = PySurface_AsSurface(pysrcb);
|
|
dst = PySurface_AsSurface(pydst);
|
|
img = PySurface_AsSurface(pyimg);
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
|
|
srcapixels = (unsigned char *) srca->pixels;
|
|
srcbpixels = (unsigned char *) srcb->pixels;
|
|
dstpixels = (unsigned char *) dst->pixels;
|
|
imgpixels = (unsigned char *) img->pixels;
|
|
srcapitch = srca->pitch;
|
|
srcbpitch = srcb->pitch;
|
|
dstpitch = dst->pitch;
|
|
imgpitch = img->pitch;
|
|
|
|
dstw = dst->w;
|
|
dsth = dst->h;
|
|
|
|
for (y = 0; y < dsth; y++) {
|
|
|
|
unsigned int *dp = (unsigned int *)(dstpixels + dstpitch * y);
|
|
unsigned int *dpe = dp + dstw;
|
|
|
|
unsigned int *sap = (unsigned int *)(srcapixels + srcapitch * y);
|
|
unsigned int *sbp = (unsigned int *)(srcbpixels + srcbpitch * y);
|
|
|
|
unsigned char *ip = (unsigned char *)(imgpixels + imgpitch * y);
|
|
ip += alpha_off;
|
|
|
|
while (dp < dpe) {
|
|
unsigned char alpha = (unsigned char) amap[*ip];
|
|
ip += 4;
|
|
|
|
unsigned int sal = *sap++;
|
|
unsigned int sbl = *sbp++;
|
|
|
|
unsigned int sah = (sal >> 8) & 0xff00ff;
|
|
unsigned int sbh = (sbl >> 8) & 0xff00ff;
|
|
|
|
sal &= 0xff00ff;
|
|
sbl &= 0xff00ff;
|
|
|
|
*dp++ = I(sal, sbl, alpha) | (I(sah, sbh, alpha) << 8);
|
|
}
|
|
}
|
|
|
|
Py_END_ALLOW_THREADS
|
|
}
|
|
|
|
#ifdef GCC_MMX
|
|
|
|
void imageblend32_core_mmx(PyObject *pysrca, PyObject *pysrcb,
|
|
PyObject *pydst, PyObject *pyimg,
|
|
int alpha_off, char *amap) {
|
|
|
|
SDL_Surface *srca;
|
|
SDL_Surface *srcb;
|
|
SDL_Surface *dst;
|
|
SDL_Surface *img;
|
|
|
|
int srcapitch, srcbpitch, dstpitch, imgpitch;
|
|
unsigned short dstw, dsth;
|
|
unsigned short y;
|
|
|
|
unsigned char *srcapixels;
|
|
unsigned char *srcbpixels;
|
|
unsigned char *dstpixels;
|
|
unsigned char *imgpixels;
|
|
|
|
srca = PySurface_AsSurface(pysrca);
|
|
srcb = PySurface_AsSurface(pysrcb);
|
|
dst = PySurface_AsSurface(pydst);
|
|
img = PySurface_AsSurface(pyimg);
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
|
|
srcapixels = (unsigned char *) srca->pixels;
|
|
srcbpixels = (unsigned char *) srcb->pixels;
|
|
dstpixels = (unsigned char *) dst->pixels;
|
|
imgpixels = (unsigned char *) img->pixels;
|
|
srcapitch = srca->pitch;
|
|
srcbpitch = srcb->pitch;
|
|
dstpitch = dst->pitch;
|
|
imgpitch = img->pitch;
|
|
|
|
dstw = dst->w;
|
|
dsth = dst->h;
|
|
|
|
pxor_r2r(mm5, mm5); /* 0 -> mm5 */
|
|
|
|
for (y = 0; y < dsth; y++) {
|
|
|
|
unsigned int *dp = (unsigned int *)(dstpixels + dstpitch * y);
|
|
unsigned int *dpe = dp + dstw;
|
|
|
|
unsigned int *sap = (unsigned int *)(srcapixels + srcapitch * y);
|
|
unsigned int *sbp = (unsigned int *)(srcbpixels + srcbpitch * y);
|
|
|
|
unsigned char *ip = (unsigned char *)(imgpixels + imgpitch * y);
|
|
ip += alpha_off;
|
|
|
|
while (dp < dpe) {
|
|
unsigned int alpha = (unsigned char) amap[*ip];
|
|
ip += 4;
|
|
|
|
/* form the alpha mult */
|
|
movd_m2r(alpha, mm4); /* 0000000A -> mm4 */
|
|
punpcklwd_r2r(mm4, mm4); /* 00000A0A -> mm4 */
|
|
punpckldq_r2r(mm4, mm4); /* 0A0A0A0A -> mm4 */
|
|
|
|
movd_m2r((*sbp++), mm1);
|
|
movd_m2r((*sap++), mm2);
|
|
punpcklbw_r2r(mm5, mm1); /* 0A0R0G0B -> mm1(b) */
|
|
punpcklbw_r2r(mm5, mm2); /* 0A0R0G0B -> mm2(a) */
|
|
psubw_r2r(mm2, mm1);/* a - b -> mm1 */
|
|
pmullw_r2r(mm4, mm1); /* mm1 * alpha -> mm1 */
|
|
psrlw_i2r(8, mm1); /* mm1 >> 8 -> mm1 */
|
|
paddb_r2r(mm1, mm2); /* mm1 + mm2(a) -> mm2 */
|
|
packuswb_r2r(mm5, mm2); /* ARGBARGB -> mm2 */
|
|
movd_r2m(mm2, *dp++);
|
|
}
|
|
}
|
|
|
|
emms();
|
|
Py_END_ALLOW_THREADS
|
|
}
|
|
|
|
#endif
|
|
|
|
void imageblend32_core(PyObject *pysrca, PyObject *pysrcb,
|
|
PyObject *pydst, PyObject *pyimg,
|
|
int aoff, char *amap) {
|
|
|
|
#ifdef GCC_MMX
|
|
static int checked_mmx = 0;
|
|
static int has_mmx = 0;
|
|
|
|
if (! checked_mmx) {
|
|
has_mmx = SDL_HasMMX();
|
|
checked_mmx = 1;
|
|
}
|
|
|
|
if (has_mmx) {
|
|
imageblend32_core_mmx(pysrca, pysrcb, pydst, pyimg, aoff, amap);
|
|
return;
|
|
}
|
|
|
|
#endif
|
|
|
|
imageblend32_core_std(pysrca, pysrcb, pydst, pyimg, aoff, amap);
|
|
}
|
|
|
|
|
|
void colormatrix32_core(PyObject *pysrc, PyObject *pydst,
|
|
float c00, float c01, float c02, float c03, float c04,
|
|
float c10, float c11, float c12, float c13, float c14,
|
|
float c20, float c21, float c22, float c23, float c24,
|
|
float c30, float c31, float c32, float c33, float c34) {
|
|
|
|
SDL_Surface *src;
|
|
SDL_Surface *dst;
|
|
|
|
int srcpitch, dstpitch;
|
|
unsigned short dstw, dsth;
|
|
unsigned short y;
|
|
|
|
unsigned char *srcpixels;
|
|
unsigned char *dstpixels;
|
|
|
|
src = PySurface_AsSurface(pysrc);
|
|
dst = PySurface_AsSurface(pydst);
|
|
|
|
Py_BEGIN_ALLOW_THREADS
|
|
|
|
srcpixels = (unsigned char *) src->pixels;
|
|
dstpixels = (unsigned char *) dst->pixels;
|
|
srcpitch = src->pitch;
|
|
dstpitch = dst->pitch;
|
|
|
|
dstw = dst->w;
|
|
dsth = dst->h;
|
|
|
|
int o0 = c04 * 255;
|
|
int o1 = c14 * 255;
|
|
int o2 = c24 * 255;
|
|
int o3 = c34 * 255;
|
|
|
|
for (y = 0; y < dsth; y++) {
|
|
|
|
int r;
|
|
|
|
unsigned char *dp = dstpixels + dstpitch * y;
|
|
unsigned char *dpe = dp + dstw * 4;
|
|
unsigned char *sp = srcpixels + srcpitch * y;
|
|
|
|
while (dp < dpe) {
|
|
unsigned char s0 = *sp++;
|
|
unsigned char s1 = *sp++;
|
|
unsigned char s2 = *sp++;
|
|
unsigned char s3 = *sp++;
|
|
|
|
/* *dp++ = (unsigned char) */
|
|
/* fminf(255, fmaxf(0, fmaf(s0, c00, fmaf(s1, c01, fmaf(s2, c02, fmaf(s3, c03, o0)))))); */
|
|
/* *dp++ = (unsigned char) */
|
|
/* fminf(255, fmaxf(0, fmaf(s0, c10, fmaf(s1, c11, fmaf(s2, c12, fmaf(s3, c13, o1)))))); */
|
|
/* *dp++ = (unsigned char) */
|
|
/* fminf(255, fmaxf(0, fmaf(s0, c20, fmaf(s1, c21, fmaf(s2, c22, fmaf(s3, c23, o2)))))); */
|
|
/* *dp++ = (unsigned char) */
|
|
/* fminf(255, fmaxf(0, fmaf(s0, c30, fmaf(s1, c31, fmaf(s2, c32, fmaf(s3, c33, o3)))))); */
|
|
|
|
r = o0 + (int) (c00 * s0 + c01 * s1 + c02 * s2 + c03 * s3);
|
|
if (r < 0) r = 0;
|
|
if (r > 255) r = 255;
|
|
*dp++ = r;
|
|
|
|
r = o1 + (int) (c10 * s0 + c11 * s1 + c12 * s2 + c13 * s3);
|
|
if (r < 0) r = 0;
|
|
if (r > 255) r = 255;
|
|
*dp++ = r;
|
|
|
|
r = o2 + (int) (c20 * s0 + c21 * s1 + c22 * s2 + c23 * s3);
|
|
if (r < 0) r = 0;
|
|
if (r > 255) r = 255;
|
|
*dp++ = r;
|
|
|
|
r = o3 + (int) (c30 * s0 + c31 * s1 + c32 * s2 + c33 * s3);
|
|
if (r < 0) r = 0;
|
|
if (r > 255) r = 255;
|
|
*dp++ = r;
|
|
}
|
|
}
|
|
|
|
Py_END_ALLOW_THREADS
|
|
}
|
|
|
|
void staticgray_core(PyObject *pysrc, PyObject *pydst,
|
|
int rmul, int gmul, int bmul, int amul, int shift, char *vmap) {
|
|
|
|
SDL_Surface *src;
|
|
SDL_Surface *dst;
|
|
|
|
int srcpitch, dstpitch;
|
|
unsigned short dstw, dsth;
|
|
unsigned short x, y;
|
|
|
|
unsigned char *srcpixels;
|
|
unsigned char *dstpixels;
|
|
|
|
src = PySurface_AsSurface(pysrc);
|
|
dst = PySurface_AsSurface(pydst);
|
|
|
|
Py_BEGIN_ALLOW_THREADS;
|
|
|
|
srcpixels = (unsigned char *) src->pixels;
|
|
dstpixels = (unsigned char *) dst->pixels;
|
|
srcpitch = src->pitch;
|
|
dstpitch = dst->pitch;
|
|
|
|
dstw = dst->w;
|
|
dsth = dst->h;
|
|
|
|
for (y = 0; y < dsth; y++) {
|
|
unsigned char *s = &srcpixels[y * srcpitch];
|
|
unsigned char *d = &dstpixels[y * dstpitch];
|
|
|
|
for (x = 0; x < dstw; x++) {
|
|
int sum = 0;
|
|
|
|
sum += *s++ * rmul;
|
|
sum += *s++ * gmul;
|
|
sum += *s++ * bmul;
|
|
sum += *s++ * amul;
|
|
*d++ = (unsigned char) vmap[sum >> shift];
|
|
}
|
|
}
|
|
|
|
Py_END_ALLOW_THREADS;
|
|
}
|