3084 lines
93 KiB
C
Executable File
3084 lines
93 KiB
C
Executable File
/*****************************************************************************
|
|
** $Source: /cygdrive/d/Private/_SVNROOT/bluemsx/blueMSX/Src/VideoRender/VideoRender.c,v $
|
|
**
|
|
** $Revision: 1.36 $
|
|
**
|
|
** $Date: 2007-05-22 06:23:18 $
|
|
** $Date: 2007-05-22 06:23:18 $
|
|
**
|
|
** More info: http://www.bluemsx.com
|
|
**
|
|
** Copyright (C) 2003-2006 Daniel Vik
|
|
**
|
|
** This program is free software; you can redistribute it and/or modify
|
|
** it under the terms of the GNU General Public License as published by
|
|
** the Free Software Foundation; either version 2 of the License, or
|
|
** (at your option) any later version.
|
|
**
|
|
** This program is distributed in the hope that it will be useful,
|
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
** GNU General Public License for more details.
|
|
**
|
|
** You should have received a copy of the GNU General Public License
|
|
** along with this program; if not, write to the Free Software
|
|
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
**
|
|
******************************************************************************
|
|
*/
|
|
#include "VideoRender.h"
|
|
#include "FrameBuffer.h"
|
|
#include "ArchTimer.h"
|
|
#include "Emulator.h"
|
|
#include "Scalebit.h"
|
|
#include "hq2x.h"
|
|
#include "hq3x.h"
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
#include <string.h>
|
|
|
|
#ifdef WII
|
|
static UInt16 empty_line_buffer[FB_MAX_LINE_WIDTH];
|
|
|
|
static int videoRender240(Video* pVideo, FrameBuffer* frame, int bitDepth, int zoom,
|
|
void* pDst, int dstOffset, int dstPitch, int canChangeZoom)
|
|
{
|
|
UInt16* pDst1;
|
|
int height = frame->lines;
|
|
int srcWidth = frame->maxWidth;
|
|
int h;
|
|
|
|
//dstOffset = (dstOffset & ~3) << 2;
|
|
pDst = (char*)pDst;// + zoom * dstOffset;
|
|
pDst1 = (UInt16*)pDst;
|
|
|
|
dstPitch /= (int)sizeof(UInt16);
|
|
|
|
for (h = 0; h < height; h+=2) {
|
|
UInt16* pDst1old = pDst1;
|
|
UInt16* pSrc1;
|
|
UInt16* pSrc2;
|
|
UInt16* pSrc3;
|
|
UInt16* pSrc4;
|
|
if (frame->interlace != INTERLACE_ODD) {
|
|
pSrc1 = frame->line[h].buffer;
|
|
pSrc2 = frame->line[h].buffer;
|
|
pSrc3 = frame->line[h+1].buffer;
|
|
pSrc4 = frame->line[h+1].buffer;
|
|
}else{
|
|
pSrc1 = h? frame->line[h-1].buffer : empty_line_buffer;
|
|
pSrc2 = frame->line[h].buffer;
|
|
pSrc3 = frame->line[h].buffer;
|
|
pSrc4 = frame->line[h+1].buffer;
|
|
}
|
|
|
|
if (frame->line[h].doubleWidth) {
|
|
int width = srcWidth / 4 * 2;
|
|
while (width--) {
|
|
*pDst1++ = *pSrc1++;
|
|
*pDst1++ = *pSrc1++;
|
|
*pDst1++ = *pSrc1++;
|
|
*pDst1++ = *pSrc1++;
|
|
*pDst1++ = *pSrc2++;
|
|
*pDst1++ = *pSrc2++;
|
|
*pDst1++ = *pSrc2++;
|
|
*pDst1++ = *pSrc2++;
|
|
*pDst1++ = *pSrc3++;
|
|
*pDst1++ = *pSrc3++;
|
|
*pDst1++ = *pSrc3++;
|
|
*pDst1++ = *pSrc3++;
|
|
*pDst1++ = *pSrc4++;
|
|
*pDst1++ = *pSrc4++;
|
|
*pDst1++ = *pSrc4++;
|
|
*pDst1++ = *pSrc4++;
|
|
}
|
|
}
|
|
else {
|
|
int width = srcWidth / 4;
|
|
while (width--) {
|
|
*pDst1++ = *pSrc1;
|
|
*pDst1++ = *pSrc1++;
|
|
*pDst1++ = *pSrc1;
|
|
*pDst1++ = *pSrc1++;
|
|
*pDst1++ = *pSrc2;
|
|
*pDst1++ = *pSrc2++;
|
|
*pDst1++ = *pSrc2;
|
|
*pDst1++ = *pSrc2++;
|
|
*pDst1++ = *pSrc3;
|
|
*pDst1++ = *pSrc3++;
|
|
*pDst1++ = *pSrc3;
|
|
*pDst1++ = *pSrc3++;
|
|
*pDst1++ = *pSrc4;
|
|
*pDst1++ = *pSrc4++;
|
|
*pDst1++ = *pSrc4;
|
|
*pDst1++ = *pSrc4++;
|
|
|
|
*pDst1++ = *pSrc1;
|
|
*pDst1++ = *pSrc1++;
|
|
*pDst1++ = *pSrc1;
|
|
*pDst1++ = *pSrc1++;
|
|
*pDst1++ = *pSrc2;
|
|
*pDst1++ = *pSrc2++;
|
|
*pDst1++ = *pSrc2;
|
|
*pDst1++ = *pSrc2++;
|
|
*pDst1++ = *pSrc3;
|
|
*pDst1++ = *pSrc3++;
|
|
*pDst1++ = *pSrc3;
|
|
*pDst1++ = *pSrc3++;
|
|
*pDst1++ = *pSrc4;
|
|
*pDst1++ = *pSrc4++;
|
|
*pDst1++ = *pSrc4;
|
|
*pDst1++ = *pSrc4++;
|
|
}
|
|
}
|
|
|
|
pDst1 = pDst1old + dstPitch * 4;
|
|
}
|
|
return zoom;
|
|
}
|
|
|
|
static int videoRender480(Video* pVideo, FrameBuffer* frame, int bitDepth, int zoom,
|
|
void* pDst, int dstOffset, int dstPitch, int canChangeZoom)
|
|
{
|
|
UInt16* pDst1;
|
|
int height = frame->lines;
|
|
int srcWidth = frame->maxWidth;
|
|
int h;
|
|
|
|
//dstOffset = (dstOffset & ~3) << 2;
|
|
pDst = (char*)pDst;// + zoom * dstOffset;
|
|
pDst1 = (UInt16*)pDst;
|
|
|
|
dstPitch /= (int)sizeof(UInt16);
|
|
|
|
for (h = 0; h < height; h+=4) {
|
|
UInt16* pDst1old = pDst1;
|
|
UInt16* pSrc1 = frame->line[h].buffer;
|
|
UInt16* pSrc2 = frame->line[h+1].buffer;
|
|
UInt16* pSrc3 = frame->line[h+2].buffer;
|
|
UInt16* pSrc4 = frame->line[h+3].buffer;
|
|
|
|
if (frame->line[h].doubleWidth) {
|
|
int width = srcWidth / 4 * 2;
|
|
while (width--) {
|
|
*pDst1++ = *pSrc1++;
|
|
*pDst1++ = *pSrc1++;
|
|
*pDst1++ = *pSrc1++;
|
|
*pDst1++ = *pSrc1++;
|
|
*pDst1++ = *pSrc2++;
|
|
*pDst1++ = *pSrc2++;
|
|
*pDst1++ = *pSrc2++;
|
|
*pDst1++ = *pSrc2++;
|
|
*pDst1++ = *pSrc3++;
|
|
*pDst1++ = *pSrc3++;
|
|
*pDst1++ = *pSrc3++;
|
|
*pDst1++ = *pSrc3++;
|
|
*pDst1++ = *pSrc4++;
|
|
*pDst1++ = *pSrc4++;
|
|
*pDst1++ = *pSrc4++;
|
|
*pDst1++ = *pSrc4++;
|
|
}
|
|
}
|
|
else {
|
|
int width = srcWidth / 4;
|
|
while (width--) {
|
|
*pDst1++ = *pSrc1;
|
|
*pDst1++ = *pSrc1++;
|
|
*pDst1++ = *pSrc1;
|
|
*pDst1++ = *pSrc1++;
|
|
*pDst1++ = *pSrc2;
|
|
*pDst1++ = *pSrc2++;
|
|
*pDst1++ = *pSrc2;
|
|
*pDst1++ = *pSrc2++;
|
|
*pDst1++ = *pSrc3;
|
|
*pDst1++ = *pSrc3++;
|
|
*pDst1++ = *pSrc3;
|
|
*pDst1++ = *pSrc3++;
|
|
*pDst1++ = *pSrc4;
|
|
*pDst1++ = *pSrc4++;
|
|
*pDst1++ = *pSrc4;
|
|
*pDst1++ = *pSrc4++;
|
|
|
|
*pDst1++ = *pSrc1;
|
|
*pDst1++ = *pSrc1++;
|
|
*pDst1++ = *pSrc1;
|
|
*pDst1++ = *pSrc1++;
|
|
*pDst1++ = *pSrc2;
|
|
*pDst1++ = *pSrc2++;
|
|
*pDst1++ = *pSrc2;
|
|
*pDst1++ = *pSrc2++;
|
|
*pDst1++ = *pSrc3;
|
|
*pDst1++ = *pSrc3++;
|
|
*pDst1++ = *pSrc3;
|
|
*pDst1++ = *pSrc3++;
|
|
*pDst1++ = *pSrc4;
|
|
*pDst1++ = *pSrc4++;
|
|
*pDst1++ = *pSrc4;
|
|
*pDst1++ = *pSrc4++;
|
|
}
|
|
}
|
|
|
|
pDst1 = pDst1old + dstPitch * 4;
|
|
}
|
|
return zoom;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
**
|
|
** Public interface methods
|
|
**
|
|
******************************************************************************
|
|
*/
|
|
|
|
int videoRender(Video* pVideo, FrameBuffer* frame, int bitDepth, int zoom,
|
|
void* pDst, int dstOffset, int dstPitch, int canChangeZoom)
|
|
{
|
|
if (frame == NULL) {
|
|
return zoom;
|
|
}
|
|
|
|
if (frame->interlace != INTERLACE_NONE && pVideo->deInterlace) {
|
|
frame = frameBufferDeinterlace(frame);
|
|
}
|
|
|
|
if (frame->lines <= 240) {
|
|
zoom = videoRender240(pVideo, frame, bitDepth, zoom, pDst, dstOffset, dstPitch, canChangeZoom);
|
|
}
|
|
else {
|
|
zoom = videoRender480(pVideo, frame, bitDepth, zoom, pDst, dstOffset, dstPitch, canChangeZoom);
|
|
}
|
|
return zoom;
|
|
}
|
|
|
|
Video* videoCreate()
|
|
{
|
|
Video* pVideo = (Video*)calloc(1, sizeof(Video));
|
|
|
|
pVideo->deInterlace = 0;
|
|
|
|
return pVideo;
|
|
}
|
|
|
|
Video *videoCopy(const Video *original)
|
|
{
|
|
Video* pVideo = (Video*)calloc(1, sizeof(Video));
|
|
|
|
if (!pVideo)
|
|
return NULL;
|
|
|
|
pVideo->palMode = original->palMode;
|
|
pVideo->scanLinesEnable = original->scanLinesEnable;
|
|
pVideo->scanLinesPct = original->scanLinesPct;
|
|
pVideo->colorSaturationEnable = original->colorSaturationEnable;
|
|
pVideo->colorSaturationWidth = original->colorSaturationWidth;
|
|
pVideo->gamma = original->gamma;
|
|
pVideo->saturation = original->saturation;
|
|
pVideo->brightness = original->brightness;
|
|
pVideo->contrast = original->contrast;
|
|
pVideo->deInterlace = original->deInterlace;
|
|
pVideo->invertRGB = original->invertRGB;
|
|
|
|
// AK: If I'm not mistaken, tables are immutable (or at least being used as
|
|
// such)
|
|
|
|
pVideo->pRgbTable16 = original->pRgbTable16;
|
|
pVideo->pRgbTable32 = original->pRgbTable32;
|
|
|
|
return pVideo;
|
|
}
|
|
|
|
void videoDestroy(Video* pVideo)
|
|
{
|
|
free(pVideo);
|
|
}
|
|
|
|
void videoUpdateAll(Video* video, Properties* properties)
|
|
{
|
|
video->deInterlace = properties->video.deInterlace;
|
|
}
|
|
|
|
#else
|
|
|
|
#define RGB_MASK 0x7fff
|
|
|
|
#define MAX_RGB_COLORS (1 << 16)
|
|
|
|
static UInt32 pRgbTableColor32[MAX_RGB_COLORS];
|
|
static UInt32 pRgbTableGreen32[MAX_RGB_COLORS];
|
|
static UInt32 pRgbTableWhite32[MAX_RGB_COLORS];
|
|
static UInt32 pRgbTableAmber32[MAX_RGB_COLORS];
|
|
static UInt16 pRgbTableColor16[MAX_RGB_COLORS];
|
|
static UInt16 pRgbTableGreen16[MAX_RGB_COLORS];
|
|
static UInt16 pRgbTableWhite16[MAX_RGB_COLORS];
|
|
static UInt16 pRgbTableAmber16[MAX_RGB_COLORS];
|
|
|
|
#define ABS(a) ((a) < 0 ? -1 * (a) : (a))
|
|
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
|
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
|
|
|
|
|
static int gammaTable[3 * 256];
|
|
|
|
static void generateGammaTable(Video* pVideo)
|
|
{
|
|
int i;
|
|
for (i = 0; i < 3 * 256; i++) {
|
|
DoubleT value = (i - 256 + pVideo->brightness) * pVideo->contrast;
|
|
gammaTable[i] = 6;
|
|
if (value > 0) {
|
|
DoubleT factor = pow(255., pVideo->gamma - 1.);
|
|
value = (DoubleT)(factor * pow(value, pVideo->gamma));
|
|
if (value > 0) {
|
|
int gamma = (int)value;
|
|
gammaTable[i] = MAX(6, MIN(247, gamma));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#define videoGamma(index) gammaTable[index + 256]
|
|
|
|
static void initRGBTable(Video* pVideo)
|
|
{
|
|
int rgb;
|
|
|
|
generateGammaTable(pVideo);
|
|
|
|
for (rgb = 0; rgb < MAX_RGB_COLORS; rgb++) {
|
|
int R = 8 * ((rgb >> 10) & 0x01f);
|
|
int G = 8 * ((rgb >> 5) & 0x01f);
|
|
int B = 8 * ((rgb >> 0) & 0x01f);
|
|
int L = 0;
|
|
|
|
int Y = (int)(0.2989*R + 0.5866*G + 0.1145*B);
|
|
int Cb = B - Y;
|
|
int Cr = R - Y;
|
|
|
|
if (pVideo->saturation < 0.999 || pVideo->saturation > 1.001) {
|
|
Cb = (int)(Cb * pVideo->saturation);
|
|
Cr = (int)(Cr * pVideo->saturation);
|
|
Y = MAX(0, MIN(255, Y));
|
|
Cb = MAX(-256, MIN(255, Cb));
|
|
Cr = MAX(-256, MIN(255, Cr));
|
|
R = Cr + Y;
|
|
G = (int)(Y - (0.1145/0.5866)*Cb - (0.2989/0.5866)*Cr);
|
|
B = Cb + Y;
|
|
R = MIN(255, MAX(0, R));
|
|
G = MIN(255, MAX(0, G));
|
|
B = MIN(255, MAX(0, B));
|
|
}
|
|
|
|
R = videoGamma(R);
|
|
G = videoGamma(G);
|
|
B = videoGamma(B);
|
|
L = videoGamma(Y);
|
|
|
|
if (pVideo->invertRGB) {
|
|
pRgbTableColor32[rgb] = (R << 0) | (G << 8) | (B << 16);
|
|
}
|
|
else {
|
|
pRgbTableColor32[rgb] = (R << 16) | (G << 8) | (B << 0);
|
|
}
|
|
pRgbTableColor16[rgb] = ((R >> 3) << 11) | ((G >> 2) << 5) | (B >> 3);
|
|
|
|
pRgbTableGreen32[rgb] = 0x100010 | (L << 8);
|
|
pRgbTableGreen16[rgb] = 0x0801 | (UInt16)((L >> 2) << 5);
|
|
|
|
pRgbTableWhite32[rgb] = (L << 16) | (L << 8) | (L << 0);
|
|
pRgbTableWhite16[rgb] = (UInt16)(((L >> 3) << 11) | ((L >> 2) << 5) | (L >> 3));
|
|
|
|
if (pVideo->invertRGB) {
|
|
pRgbTableAmber32[rgb] = (L << 0) | ((L * 176 / 255) << 8);
|
|
}
|
|
else {
|
|
pRgbTableAmber32[rgb] = (L << 16) | ((L * 176 / 255) << 8);
|
|
}
|
|
pRgbTableAmber16[rgb] = ((L >> 3) << 11) | (((L * 176 / 255) >> 2) << 5);
|
|
}
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
**
|
|
** PAL emulation rendering routines
|
|
**
|
|
******************************************************************************
|
|
*/
|
|
static void copySharpPAL_2x2_16(FrameBuffer* frame, void* pDestination, int dstPitch, UInt16* rgbTable, UInt32 rnd)
|
|
{
|
|
static UInt32 rndVal = 51;
|
|
UInt16* pDst1 = (UInt16*)pDestination;
|
|
UInt16* pDst2 = pDst1 + dstPitch / (int)sizeof(UInt16);
|
|
UInt16* pDst3 = pDst2;
|
|
int height = frame->lines;
|
|
int srcWidth = frame->maxWidth;
|
|
int h;
|
|
|
|
rndVal *= 13;
|
|
rnd *= rndVal;
|
|
|
|
dstPitch /= (int)sizeof(UInt16);
|
|
|
|
if (frame->interlace == INTERLACE_ODD) {
|
|
pDst1 += dstPitch;
|
|
pDst2 += dstPitch;
|
|
height--;
|
|
}
|
|
|
|
for (h = 0; h < height; h++) {
|
|
UInt16* pSrc = frame->line[h].buffer;
|
|
UInt16 colCur = (rgbTable[pSrc[0]] & 0xe79c) >> 2;
|
|
UInt16 colPrev = colCur;
|
|
int dstIndex = 0;
|
|
|
|
if (frame->line[h].doubleWidth) {
|
|
int width = srcWidth * 2;
|
|
int w;
|
|
for (w = 0; w < width;) {
|
|
UInt16 colNext;
|
|
UInt16 colRgb1;
|
|
UInt16 colRgb2;
|
|
UInt16 noise;
|
|
|
|
colNext = (rgbTable[pSrc[w++]] & 0xe79c) >> 2;
|
|
colRgb1 = (colPrev + colNext + 2 * colCur) & 0xe79c;
|
|
|
|
colPrev = colCur;
|
|
colCur = colNext;
|
|
|
|
colNext = (rgbTable[pSrc[w++]] & 0xe79c) >> 2;
|
|
colRgb2 = (colPrev + colNext + 2 * colCur) & 0xe79c;
|
|
|
|
colPrev = colCur;
|
|
colCur = colNext;
|
|
|
|
noise = (UInt16)(rnd >> 31) * 0x0821;
|
|
pDst2[dstIndex] = colRgb1 + noise;
|
|
pDst1[dstIndex] = (((pDst3[dstIndex] >> 1) & 0x7bef) + ((colRgb1 >> 1) & 0x7bef));
|
|
dstIndex++;
|
|
pDst2[dstIndex] = colRgb2 + noise;
|
|
pDst1[dstIndex] = (((pDst3[dstIndex] >> 3) & 0x7bef) + ((colRgb2 >> 1) & 0x7bef));
|
|
dstIndex++;
|
|
|
|
rnd *= 23;
|
|
}
|
|
}
|
|
else {
|
|
int width = srcWidth;
|
|
int w;
|
|
for (w = 0; w < width;) {
|
|
UInt16 colNext;
|
|
UInt16 colRgb1;
|
|
UInt16 colRgb2;
|
|
UInt16 noise;
|
|
|
|
colNext = (rgbTable[pSrc[w++]] & 0xe79c) >> 2;
|
|
colRgb1 = (colNext + 3 * colCur) & 0xe79c;
|
|
colRgb2 = (colCur + 3 * colNext) & 0xe79c;
|
|
|
|
colCur = colNext;
|
|
|
|
noise = (UInt16)(rnd >> 31) * 0x0821;
|
|
pDst2[dstIndex] = colRgb1 + noise;
|
|
pDst1[dstIndex] = (((pDst3[dstIndex] >> 1) & 0x7bef) + ((colRgb1 >> 1) & 0x7bef));
|
|
dstIndex++;
|
|
pDst2[dstIndex] = colRgb2 + noise;
|
|
pDst1[dstIndex] = (((pDst3[dstIndex] >> 1) & 0x7bef) + ((colRgb2 >> 1) & 0x7bef));
|
|
dstIndex++;
|
|
|
|
rnd *= 23;
|
|
}
|
|
}
|
|
|
|
pDst3 = pDst2;
|
|
pDst1 += dstPitch * 2;
|
|
pDst2 += dstPitch * 2;
|
|
}
|
|
}
|
|
|
|
static void copySharpPAL_2x2_32(FrameBuffer* frame, void* pDestination, int dstPitch, UInt32* rgbTable, UInt32 rnd)
|
|
{
|
|
static UInt32 rndVal = 51;
|
|
UInt32* pDst1 = (UInt32*)pDestination;
|
|
UInt32* pDst2 = pDst1 + dstPitch / (int)sizeof(UInt32);
|
|
UInt32* pDst3 = pDst2;
|
|
int height = frame->lines;
|
|
int srcWidth = frame->maxWidth;
|
|
int h;
|
|
|
|
rndVal *= 13;
|
|
rnd *= rndVal;
|
|
|
|
dstPitch /= (int)sizeof(UInt32);
|
|
|
|
if (frame->interlace == INTERLACE_ODD) {
|
|
pDst1 += dstPitch;
|
|
pDst2 += dstPitch;
|
|
height--;
|
|
}
|
|
|
|
for (h = 0; h < height; h++) {
|
|
UInt16* pSrc = frame->line[h].buffer;
|
|
UInt32 colCur = (rgbTable[pSrc[0]] & 0xfcfcfc) >> 2;
|
|
UInt32 colPrev = colCur;
|
|
int dstIndex = 0;
|
|
|
|
if (frame->line[h].doubleWidth) {
|
|
int width = srcWidth * 2;
|
|
int w;
|
|
for (w = 0; w < width;) {
|
|
UInt32 colNext;
|
|
UInt32 colRgb1;
|
|
UInt32 colRgb2;
|
|
UInt32 noise;
|
|
|
|
colNext = (rgbTable[pSrc[w++]] & 0xfcfcfc) >> 2;
|
|
colRgb1 = (colPrev + colNext + 2 * colCur) & 0xfcfcfc;
|
|
|
|
colPrev = colCur;
|
|
colCur = colNext;
|
|
|
|
colNext = (rgbTable[pSrc[w++]] & 0xfcfcfc) >> 2;
|
|
colRgb2 = (colPrev + colNext + 2 * colCur) & 0xfcfcfc;
|
|
|
|
colPrev = colCur;
|
|
colCur = colNext;
|
|
|
|
noise = (rnd >> 29) * 0x10101;
|
|
pDst2[dstIndex] = colRgb1 + noise;
|
|
pDst1[dstIndex] = ((pDst3[dstIndex] >> 1) & 0x7f7f7f) + ((colRgb1 >> 1) & 0x7f7f7f);
|
|
dstIndex++;
|
|
pDst2[dstIndex] = colRgb2 + noise;
|
|
pDst1[dstIndex] = ((pDst3[dstIndex] >> 1) & 0x7f7f7f) + ((colRgb2 >> 1) & 0x7f7f7f);
|
|
dstIndex++;
|
|
|
|
rnd *= 23;
|
|
}
|
|
}
|
|
else {
|
|
int width = srcWidth;
|
|
int w;
|
|
for (w = 0; w < width;) {
|
|
UInt32 colNext;
|
|
UInt32 colRgb1;
|
|
UInt32 colRgb2;
|
|
UInt32 noise;
|
|
|
|
colNext = (rgbTable[pSrc[w++]] & 0xfcfcfc) >> 2;
|
|
colRgb1 = (colNext + 3 * colCur) & 0xfcfcfc;
|
|
colRgb2 = (colCur + 3 * colNext) & 0xfcfcfc;
|
|
|
|
colCur = colNext;
|
|
|
|
noise = (rnd >> 29) * 0x10101;
|
|
pDst2[dstIndex] = colRgb1 + noise;
|
|
pDst1[dstIndex] = ((pDst3[dstIndex] >> 1) & 0x7f7f7f) + ((colRgb1 >> 1) & 0x7f7f7f);
|
|
dstIndex++;
|
|
pDst2[dstIndex] = colRgb2 + noise;
|
|
pDst1[dstIndex] = ((pDst3[dstIndex] >> 1) & 0x7f7f7f) + ((colRgb2 >> 1) & 0x7f7f7f);
|
|
dstIndex++;
|
|
|
|
rnd *= 23;
|
|
}
|
|
}
|
|
|
|
pDst3 = pDst2;
|
|
pDst1 += dstPitch * 2;
|
|
pDst2 += dstPitch * 2;
|
|
}
|
|
}
|
|
|
|
static void copySharpPAL_2x1_16(FrameBuffer* frame, void* pDestination, int dstPitch, UInt16* rgbTable, UInt32 rnd)
|
|
{
|
|
static UInt32 rndVal = 51;
|
|
UInt16* pDst1 = (UInt16*)pDestination;
|
|
int height = frame->lines;
|
|
int srcWidth = frame->maxWidth;
|
|
int h;
|
|
|
|
rndVal *= 13;
|
|
rnd *= rndVal;
|
|
|
|
dstPitch /= (int)sizeof(UInt16);
|
|
|
|
if (frame->interlace == INTERLACE_ODD) {
|
|
pDst1 += dstPitch;
|
|
height--;
|
|
}
|
|
|
|
for (h = 0; h < height; h++) {
|
|
UInt16* pSrc = frame->line[h].buffer;
|
|
UInt16 colCur = (rgbTable[pSrc[0]] & 0xe79c) >> 2;
|
|
UInt16 colPrev = colCur;
|
|
int dstIndex = 0;
|
|
|
|
if (frame->line[h].doubleWidth) {
|
|
int width = srcWidth * 2;
|
|
int w;
|
|
for (w = 0; w < width;) {
|
|
UInt16 colNext;
|
|
UInt16 colRgb1;
|
|
UInt16 colRgb2;
|
|
UInt16 noise;
|
|
|
|
colNext = (rgbTable[pSrc[w++]] & 0xe79c) >> 2;
|
|
colRgb1 = (colPrev + colNext + 2 * colCur) & 0xe79c;
|
|
|
|
colPrev = colCur;
|
|
colCur = colNext;
|
|
|
|
colNext = (rgbTable[pSrc[w++]] & 0xe79c) >> 2;
|
|
colRgb2 = (colPrev + colNext + 2 * colCur) & 0xe79c;
|
|
|
|
colPrev = colCur;
|
|
colCur = colNext;
|
|
|
|
noise = (UInt16)((rnd >> 31) * 0x821);
|
|
pDst1[dstIndex++] = colRgb1 + noise;
|
|
pDst1[dstIndex++] = colRgb2 + noise;
|
|
|
|
rnd *= 23;
|
|
}
|
|
}
|
|
else {
|
|
int width = srcWidth;
|
|
int w;
|
|
for (w = 0; w < width;) {
|
|
UInt16 colNext;
|
|
UInt16 colRgb1;
|
|
UInt16 colRgb2;
|
|
UInt16 noise;
|
|
|
|
colNext = (rgbTable[pSrc[w++]] & 0xe79c) >> 2;
|
|
colRgb1 = (colPrev + colNext + 2 * colCur) & 0xe79c;
|
|
|
|
colPrev = colCur;
|
|
colCur = colNext;
|
|
|
|
colNext = (rgbTable[pSrc[w++]] & 0xe79c) >> 2;
|
|
colRgb2 = (colPrev + colNext + 2 * colCur) & 0xe79c;
|
|
|
|
colPrev = colCur;
|
|
colCur = colNext;
|
|
|
|
noise = (UInt16)((rnd >> 31) * 0x821);
|
|
pDst1[dstIndex++] = colRgb1 + noise;
|
|
pDst1[dstIndex++] = colRgb2 + noise;
|
|
|
|
rnd *= 23;
|
|
}
|
|
}
|
|
|
|
pDst1 += dstPitch;
|
|
}
|
|
}
|
|
|
|
|
|
static void copySharpPAL_2x1_32(FrameBuffer* frame, void* pDestination, int dstPitch, UInt32* rgbTable, UInt32 rnd)
|
|
{
|
|
static UInt32 rndVal = 51;
|
|
UInt32* pDst1 = (UInt32*)pDestination;
|
|
int height = frame->lines;
|
|
int srcWidth = frame->maxWidth;
|
|
int h;
|
|
|
|
rndVal *= 13;
|
|
rnd *= rndVal;
|
|
|
|
dstPitch /= (int)sizeof(UInt32);
|
|
|
|
if (frame->interlace == INTERLACE_ODD) {
|
|
pDst1 += dstPitch;
|
|
height--;
|
|
}
|
|
|
|
for (h = 0; h < height; h++) {
|
|
UInt16* pSrc = frame->line[h].buffer;
|
|
UInt32 colCur = (rgbTable[pSrc[0]] & 0xfcfcfc) >> 2;
|
|
UInt32 colPrev = colCur;
|
|
int dstIndex = 0;
|
|
|
|
if (frame->line[h].doubleWidth) {
|
|
int width = srcWidth * 2;
|
|
int w;
|
|
for (w = 0; w < width;) {
|
|
UInt32 colNext;
|
|
UInt32 colRgb1;
|
|
UInt32 colRgb2;
|
|
UInt32 noise;
|
|
|
|
colNext = (rgbTable[pSrc[w++]] & 0xfcfcfc) >> 2;
|
|
colRgb1 = (colPrev + colNext + 2 * colCur) & 0xfcfcfc;
|
|
|
|
colPrev = colCur;
|
|
colCur = colNext;
|
|
|
|
colNext = (rgbTable[pSrc[w++]] & 0xfcfcfc) >> 2;
|
|
colRgb2 = (colPrev + colNext + 2 * colCur) & 0xfcfcfc;
|
|
|
|
colPrev = colCur;
|
|
colCur = colNext;
|
|
|
|
noise = (rnd >> 29) * 0x10101;
|
|
pDst1[dstIndex++] = colRgb1 + noise;
|
|
pDst1[dstIndex++] = colRgb2 + noise;
|
|
|
|
rnd *= 23;
|
|
}
|
|
}
|
|
else {
|
|
int width = srcWidth;
|
|
int w;
|
|
for (w = 0; w < width;) {
|
|
UInt32 colNext;
|
|
UInt32 colRgb1;
|
|
UInt32 colRgb2;
|
|
UInt32 noise;
|
|
|
|
colNext = (rgbTable[pSrc[w++]] & 0xfcfcfc) >> 2;
|
|
colRgb1 = (colPrev + 3 * colCur) & 0xfcfcfc;
|
|
colRgb2 = (colNext + 3 * colCur) & 0xfcfcfc;
|
|
|
|
colPrev = colCur;
|
|
colCur = colNext;
|
|
|
|
noise = (rnd >> 29) * 0x10101;
|
|
pDst1[dstIndex++] = colRgb1 + noise;
|
|
pDst1[dstIndex++] = colRgb2 + noise;
|
|
|
|
rnd *= 23;
|
|
colCur = colNext;
|
|
}
|
|
}
|
|
|
|
pDst1 += dstPitch;
|
|
}
|
|
}
|
|
|
|
static void copyMonitorPAL_2x2_16(FrameBuffer* frame, void* pDestination, int dstPitch, UInt16* rgbTable, UInt32 rnd)
|
|
{
|
|
static UInt32 rndVal = 51;
|
|
UInt16* pDst1 = (UInt16*)pDestination;
|
|
UInt16* pDst2 = pDst1 + dstPitch / (int)sizeof(UInt16);
|
|
UInt16* pDst3 = pDst2;
|
|
int height = frame->lines;
|
|
int srcWidth = frame->maxWidth;
|
|
int h;
|
|
|
|
rndVal *= 13;
|
|
rnd *= rndVal;
|
|
|
|
dstPitch /= (int)sizeof(UInt16);
|
|
|
|
if (frame->interlace == INTERLACE_ODD) {
|
|
pDst1 += dstPitch;
|
|
pDst2 += dstPitch;
|
|
height--;
|
|
}
|
|
|
|
for (h = 0; h < height; h++) {
|
|
UInt16* pSrc = frame->line[h].buffer;
|
|
UInt16 colCur = (rgbTable[pSrc[0]] & 0xe79c) >> 2;
|
|
UInt16 colPrev = colCur;
|
|
int dstIndex = 0;
|
|
|
|
if (frame->line[h].doubleWidth) {
|
|
int width = srcWidth * 2;
|
|
int w;
|
|
for (w = 0; w < width;) {
|
|
UInt16 colNext;
|
|
UInt16 colRgb1;
|
|
UInt16 colRgb2;
|
|
UInt16 noise;
|
|
|
|
colNext = (rgbTable[pSrc[w++]] & 0xe79c) >> 2;
|
|
colRgb1 = (colPrev + 3 * colCur) & 0xe79c;
|
|
|
|
colPrev = colCur;
|
|
colCur = colNext;
|
|
|
|
colNext = (rgbTable[pSrc[w++]] & 0xe79c) >> 2;
|
|
colRgb2 = (colNext + 3 * colCur) & 0xe79c;
|
|
|
|
colPrev = colCur;
|
|
colCur = colNext;
|
|
|
|
noise = (UInt16)(rnd >> 31) * 0x0821;
|
|
pDst2[dstIndex] = colRgb1 + noise;
|
|
pDst1[dstIndex] = ((pDst3[dstIndex] >> 1) & 0x7bef) + ((colRgb1 >> 1) & 0x7bef);
|
|
pDst1[dstIndex] = ((pDst1[dstIndex] >> 1) & 0x7bef) + ((colRgb1 >> 1) & 0x7bef);
|
|
dstIndex++;
|
|
pDst2[dstIndex] = colRgb2 + noise;
|
|
pDst1[dstIndex] = ((pDst3[dstIndex] >> 1) & 0x7f7f7f) + ((colRgb2 >> 1) & 0x7f7f7f);
|
|
pDst1[dstIndex] = ((pDst1[dstIndex] >> 1) & 0x7f7f7f) + ((colRgb2 >> 1) & 0x7f7f7f);
|
|
dstIndex++;
|
|
|
|
rnd *= 23;
|
|
}
|
|
}
|
|
else {
|
|
int width = srcWidth;
|
|
int w;
|
|
for (w = 0; w < width;) {
|
|
UInt16 colRgb1;
|
|
UInt16 colRgb2;
|
|
UInt16 colNext;
|
|
UInt16 noise;
|
|
|
|
colNext = (rgbTable[pSrc[w++]] & 0xfcfcfc) >> 2;
|
|
colRgb1 = (3 * colCur + colNext) & 0xfcfcfc;
|
|
colRgb2 = (4 * colNext) & 0xfcfcfc;
|
|
|
|
colCur = colNext;
|
|
|
|
noise = (UInt16)(rnd >> 31) * 0x0821;
|
|
pDst2[dstIndex] = colRgb1 + noise;
|
|
pDst1[dstIndex] = ((pDst3[dstIndex] >> 1) & 0x7bef) + ((colRgb1 >> 1) & 0x7bef);
|
|
pDst1[dstIndex] = ((pDst1[dstIndex] >> 1) & 0x7bef) + ((colRgb1 >> 1) & 0x7bef);
|
|
dstIndex++;
|
|
pDst2[dstIndex] = colRgb2 + noise;
|
|
pDst1[dstIndex] = ((pDst3[dstIndex] >> 1) & 0x7bef) + ((colRgb2 >> 1) & 0x7bef);
|
|
pDst1[dstIndex] = ((pDst1[dstIndex] >> 1) & 0x7bef) + ((colRgb2 >> 1) & 0x7bef);
|
|
dstIndex++;
|
|
|
|
rnd *= 23;
|
|
}
|
|
}
|
|
|
|
pDst3 = pDst2;
|
|
pDst1 += dstPitch * 2;
|
|
pDst2 += dstPitch * 2;
|
|
}
|
|
}
|
|
|
|
static void copyMonitorPAL_2x2_32(FrameBuffer* frame, void* pDestination, int dstPitch, UInt32* rgbTable, UInt32 rnd)
|
|
{
|
|
static UInt32 rndVal = 51;
|
|
UInt32* pDst1 = (UInt32*)pDestination;
|
|
UInt32* pDst2 = pDst1 + dstPitch / (int)sizeof(UInt32);
|
|
UInt32* pDst3 = pDst2;
|
|
int height = frame->lines;
|
|
int srcWidth = frame->maxWidth;
|
|
int h;
|
|
|
|
rndVal *= 13;
|
|
rnd *= rndVal;
|
|
|
|
dstPitch /= (int)sizeof(UInt32);
|
|
|
|
if (frame->interlace == INTERLACE_ODD) {
|
|
pDst1 += dstPitch;
|
|
pDst2 += dstPitch;
|
|
height--;
|
|
}
|
|
|
|
for (h = 0; h < height; h++) {
|
|
UInt16* pSrc = frame->line[h].buffer;
|
|
UInt32 colCur = (rgbTable[pSrc[0]] & 0xfcfcfc) >> 2;
|
|
UInt32 colPrev = colCur;
|
|
int dstIndex = 0;
|
|
|
|
if (frame->line[h].doubleWidth) {
|
|
int width = srcWidth * 2;
|
|
int w;
|
|
for (w = 0; w < width;) {
|
|
UInt32 colNext;
|
|
UInt32 colRgb1;
|
|
UInt32 colRgb2;
|
|
UInt32 noise;
|
|
|
|
colNext = (rgbTable[pSrc[w++]] & 0xfcfcfc) >> 2;
|
|
colRgb1 = (colPrev + 3 * colCur) & 0xfcfcfc;
|
|
|
|
colPrev = colCur;
|
|
colCur = colNext;
|
|
|
|
colNext = (rgbTable[pSrc[w++]] & 0xfcfcfc) >> 2;
|
|
colRgb2 = (colNext + 3 * colCur) & 0xfcfcfc;
|
|
|
|
colPrev = colCur;
|
|
colCur = colNext;
|
|
|
|
noise = (rnd >> 30) * 0x10101;
|
|
pDst2[dstIndex] = colRgb1 + noise;
|
|
pDst1[dstIndex] = ((pDst3[dstIndex] >> 1) & 0x7f7f7f) + ((colRgb1 >> 1) & 0x7f7f7f);
|
|
pDst1[dstIndex] = ((pDst1[dstIndex] >> 1) & 0x7f7f7f) + ((colRgb1 >> 1) & 0x7f7f7f);
|
|
dstIndex++;
|
|
pDst2[dstIndex] = colRgb2 + noise;
|
|
pDst1[dstIndex] = ((pDst3[dstIndex] >> 1) & 0x7f7f7f) + ((colRgb2 >> 1) & 0x7f7f7f);
|
|
pDst1[dstIndex] = ((pDst1[dstIndex] >> 1) & 0x7f7f7f) + ((colRgb2 >> 1) & 0x7f7f7f);
|
|
dstIndex++;
|
|
|
|
rnd *= 23;
|
|
}
|
|
}
|
|
else {
|
|
int width = srcWidth;
|
|
int w;
|
|
for (w = 0; w < width;) {
|
|
UInt32 colRgb1;
|
|
UInt32 colRgb2;
|
|
UInt32 colNext;
|
|
UInt32 noise;
|
|
|
|
colNext = (rgbTable[pSrc[w++]] & 0xfcfcfc) >> 2;
|
|
colRgb1 = (3 * colCur + colNext) & 0xfcfcfc;
|
|
colRgb2 = (4 * colNext) & 0xfcfcfc;
|
|
|
|
colCur = colNext;
|
|
|
|
noise = (rnd >> 30) * 0x10101;
|
|
pDst2[dstIndex] = colRgb1 + noise;
|
|
pDst1[dstIndex] = ((pDst3[dstIndex] >> 1) & 0x7f7f7f) + ((colRgb1 >> 1) & 0x7f7f7f);
|
|
pDst1[dstIndex] = ((pDst1[dstIndex] >> 1) & 0x7f7f7f) + ((colRgb1 >> 1) & 0x7f7f7f);
|
|
dstIndex++;
|
|
pDst2[dstIndex] = colRgb2 + noise;
|
|
pDst1[dstIndex] = ((pDst3[dstIndex] >> 1) & 0x7f7f7f) + ((colRgb2 >> 1) & 0x7f7f7f);
|
|
pDst1[dstIndex] = ((pDst1[dstIndex] >> 1) & 0x7f7f7f) + ((colRgb2 >> 1) & 0x7f7f7f);
|
|
dstIndex++;
|
|
|
|
rnd *= 23;
|
|
}
|
|
}
|
|
|
|
pDst3 = pDst2;
|
|
pDst1 += dstPitch * 2;
|
|
pDst2 += dstPitch * 2;
|
|
}
|
|
}
|
|
|
|
static void copyMonitorPAL_2x1_16(FrameBuffer* frame, void* pDestination, int dstPitch, UInt16* rgbTable, UInt32 rnd)
|
|
{
|
|
static UInt32 rndVal = 51;
|
|
UInt16* pDst1 = (UInt16*)pDestination;
|
|
int height = frame->lines;
|
|
int srcWidth = frame->maxWidth;
|
|
int h;
|
|
|
|
rndVal *= 13;
|
|
rnd *= rndVal;
|
|
|
|
dstPitch /= (int)sizeof(UInt16);
|
|
|
|
if (frame->interlace == INTERLACE_ODD) {
|
|
pDst1 += dstPitch;
|
|
height--;
|
|
}
|
|
|
|
for (h = 0; h < height; h++) {
|
|
UInt16* pSrc = frame->line[h].buffer;
|
|
UInt16 colCur = (rgbTable[pSrc[0]] & 0xe79c) >> 2;
|
|
int dstIndex = 0;
|
|
|
|
if (frame->line[h].doubleWidth) {
|
|
int width = srcWidth * 2;
|
|
int w;
|
|
for (w = 0; w < width;) {
|
|
UInt16 colNext;
|
|
UInt16 colRgb1;
|
|
UInt16 colRgb2;
|
|
UInt16 noise;
|
|
|
|
colNext = (rgbTable[pSrc[w++]] & 0xe79c) >> 2;
|
|
colRgb1 = (colNext + 3 * colCur) & 0xe79c;
|
|
|
|
colCur = colNext;
|
|
|
|
colNext = (rgbTable[pSrc[w++]] & 0xe79c) >> 2;
|
|
colRgb2 = (colNext + 3 * colCur) & 0xe79c;
|
|
|
|
colCur = colNext;
|
|
|
|
noise = (UInt16)(rnd >> 31) * 0x0821;
|
|
pDst1[dstIndex++] = colRgb1 + noise;
|
|
pDst1[dstIndex++] = colRgb2 + noise;
|
|
|
|
rnd *= 23;
|
|
}
|
|
}
|
|
else {
|
|
int width = srcWidth;
|
|
int w;
|
|
for (w = 0; w < width;) {
|
|
UInt16 colNext;
|
|
UInt16 colRgb1;
|
|
UInt16 colRgb2;
|
|
UInt16 noise;
|
|
|
|
colNext = (rgbTable[pSrc[w++]] & 0xe79c) >> 2;
|
|
colRgb1 = (colNext + 3 * colCur) & 0xe79c;
|
|
colRgb2 = (colNext * 4) & 0xe79c;
|
|
|
|
colCur = colNext;
|
|
|
|
|
|
noise = (UInt16)(rnd >> 31) * 0x0821;
|
|
pDst1[dstIndex++] = colRgb1 + noise;
|
|
pDst1[dstIndex++] = colRgb2 + noise;
|
|
rnd *= 23;
|
|
}
|
|
}
|
|
|
|
pDst1 += dstPitch;
|
|
}
|
|
}
|
|
|
|
static void copyMonitorPAL_2x1_32(FrameBuffer* frame, void* pDestination, int dstPitch, UInt32* rgbTable, UInt32 rnd)
|
|
{
|
|
static UInt32 rndVal = 51;
|
|
UInt32* pDst1 = (UInt32*)pDestination;
|
|
int height = frame->lines;
|
|
int srcWidth = frame->maxWidth;
|
|
int h;
|
|
|
|
rndVal *= 13;
|
|
rnd *= rndVal;
|
|
|
|
dstPitch /= (int)sizeof(UInt32);
|
|
|
|
if (frame->interlace == INTERLACE_ODD) {
|
|
pDst1 += dstPitch;
|
|
height--;
|
|
}
|
|
|
|
for (h = 0; h < height; h++) {
|
|
UInt16* pSrc = frame->line[h].buffer;
|
|
UInt32 colCur = (rgbTable[pSrc[0]] & 0xfcfcfc) >> 2;
|
|
int dstIndex = 0;
|
|
|
|
if (frame->line[h].doubleWidth) {
|
|
int width = srcWidth * 2;
|
|
int w;
|
|
for (w = 0; w < width;) {
|
|
UInt32 colNext;
|
|
UInt32 colRgb1;
|
|
UInt32 colRgb2;
|
|
UInt32 noise;
|
|
|
|
colNext = (rgbTable[pSrc[w++]] & 0xfcfcfc) >> 2;
|
|
colRgb1 = (colNext + 3 * colCur) & 0xfcfcfc;
|
|
|
|
colCur = colNext;
|
|
|
|
colNext = (rgbTable[pSrc[w++]] & 0xfcfcfc) >> 2;
|
|
colRgb2 = (colNext + 3 * colCur) & 0xfcfcfc;
|
|
|
|
colCur = colNext;
|
|
|
|
noise = (rnd >> 30) * 0x10101;
|
|
|
|
pDst1[dstIndex++] = colRgb1 + noise;
|
|
pDst1[dstIndex++] = colRgb2 + noise;
|
|
|
|
rnd *= 23;
|
|
}
|
|
}
|
|
else {
|
|
int width = srcWidth;
|
|
int w;
|
|
for (w = 0; w < width;) {
|
|
UInt32 colNext;
|
|
UInt32 colRgb1;
|
|
UInt32 colRgb2;
|
|
UInt32 noise;
|
|
|
|
colNext = (rgbTable[pSrc[w++]] & 0xfcfcfc) >> 2;
|
|
colRgb1 = (colNext + 3 * colCur) & 0xfcfcfc;
|
|
colRgb2 = (colNext * 4) & 0xfcfcfc;
|
|
|
|
colCur = colNext;
|
|
|
|
noise = (rnd >> 30) * 0x10101;
|
|
pDst1[dstIndex++] = colRgb1 + noise;
|
|
pDst1[dstIndex++] = colRgb2 + noise;
|
|
rnd *= 23;
|
|
}
|
|
}
|
|
|
|
pDst1 += dstPitch;
|
|
}
|
|
}
|
|
|
|
|
|
static void copyPAL_2x2_32(FrameBuffer* frame, void* pDestination, int dstPitch, UInt32* rgbTable, UInt32 rnd)
|
|
{
|
|
static UInt32 rndVal = 51;
|
|
UInt32* pDst1 = (UInt32*)pDestination;
|
|
UInt32* pDst2 = pDst1 + dstPitch / (int)sizeof(UInt32);
|
|
UInt32* pDst3 = pDst2;
|
|
int height = frame->lines;
|
|
int srcWidth = frame->maxWidth;
|
|
int h;
|
|
|
|
rndVal *= 13;
|
|
rnd *= rndVal;
|
|
|
|
dstPitch /= (int)sizeof(UInt32);
|
|
|
|
if (frame->interlace == INTERLACE_ODD) {
|
|
pDst1 += dstPitch;
|
|
pDst2 += dstPitch;
|
|
height--;
|
|
}
|
|
|
|
for (h = 0; h < height; h++) {
|
|
UInt16* pSrc = frame->line[h].buffer;
|
|
UInt32 colCur = (rgbTable[pSrc[0]] & 0xf0f0f0) >> 4;
|
|
UInt32 colPrev2 = colCur;
|
|
UInt32 colPrev1 = colCur;
|
|
UInt32 colNext1 = colCur;
|
|
int dstIndex = 0;
|
|
|
|
if (frame->line[h].doubleWidth) {
|
|
int width = srcWidth * 2;
|
|
int w;
|
|
for (w = 0; w < width;) {
|
|
UInt32 colNext2;
|
|
UInt32 colRgb1;
|
|
UInt32 colRgb2;
|
|
UInt32 colLgt;
|
|
UInt32 noise;
|
|
|
|
colNext2 = (rgbTable[pSrc[w++]] & 0xf0f0f0) >> 4;
|
|
colLgt = colCur;
|
|
|
|
colRgb1 = (colPrev2 + colNext2 + 2 * colNext1 + 4 * colPrev1 + 8 * colLgt) & 0xf0f0f0;
|
|
|
|
colPrev2 = colPrev1;
|
|
colPrev1 = colCur;
|
|
colCur = colNext1;
|
|
colNext1 = colNext2;
|
|
colNext2 = pSrc[w];
|
|
|
|
colNext2 = (rgbTable[pSrc[w++]] & 0xf0f0f0) >> 4;
|
|
colLgt = colCur;
|
|
|
|
colRgb2 = (colPrev2 + colNext2 + 2 * colPrev1 + 4 * colNext1 + 8 * colLgt) & 0xf0f0f0;
|
|
|
|
colPrev2 = colPrev1;
|
|
colPrev1 = colCur;
|
|
colCur = colNext1;
|
|
colNext1 = colNext2;
|
|
|
|
noise = (rnd >> 29) * 0x10101;
|
|
pDst2[dstIndex] = colRgb1 + noise;
|
|
pDst1[dstIndex] = (((pDst3[dstIndex] >> 1) & 0x7f7f7f) + ((colRgb1 >> 1) & 0x7f7f7f));
|
|
dstIndex++;
|
|
pDst2[dstIndex] = colRgb2 + noise;
|
|
pDst1[dstIndex] = (((pDst3[dstIndex] >> 1) & 0x7f7f7f) + ((colRgb2 >> 1) & 0x7f7f7f));
|
|
dstIndex++;
|
|
|
|
rnd *= 23;
|
|
}
|
|
}
|
|
else {
|
|
int width = srcWidth;
|
|
int w;
|
|
for (w = 0; w < width;) {
|
|
UInt32 colNext;
|
|
UInt32 colRgb1;
|
|
UInt32 colRgb2;
|
|
UInt32 colLgt;
|
|
UInt32 noise;
|
|
|
|
colNext = (rgbTable[pSrc[w++]] & 0xf0f0f0) >> 4;
|
|
colLgt = colCur;
|
|
|
|
colRgb1 = (6 * colPrev1 + 2 * colNext + 8 * colLgt) & 0xf0f0f0;
|
|
colRgb2 = (2 * colPrev1 + 6 * colNext + 8 * colLgt) & 0xf0f0f0;
|
|
|
|
noise = (rnd >> 29) * 0x10101;
|
|
pDst2[dstIndex] = colRgb1 + noise;
|
|
pDst1[dstIndex] = (((pDst3[dstIndex] >> 1) & 0x7f7f7f) + ((colRgb1 >> 1) & 0x7f7f7f));
|
|
dstIndex++;
|
|
pDst2[dstIndex] = colRgb2 + noise;
|
|
pDst1[dstIndex] = (((pDst3[dstIndex] >> 1) & 0x7f7f7f) + ((colRgb2 >> 1) & 0x7f7f7f));
|
|
dstIndex++;
|
|
|
|
rnd *= 23;
|
|
colPrev1 = colCur;
|
|
colCur = colNext;
|
|
}
|
|
}
|
|
pDst3 = pDst2;
|
|
pDst1 += dstPitch * 2;
|
|
pDst2 += dstPitch * 2;
|
|
}
|
|
}
|
|
|
|
|
|
static void copyPAL_2x1_32(FrameBuffer* frame, void* pDestination, int dstPitch, UInt32* rgbTable, UInt32 rnd)
|
|
{
|
|
static UInt32 rndVal = 51;
|
|
UInt32* pDst1 = (UInt32*)pDestination;
|
|
int height = frame->lines;
|
|
int srcWidth = frame->maxWidth;
|
|
int h;
|
|
|
|
rndVal *= 13;
|
|
rnd *= rndVal;
|
|
|
|
dstPitch /= (int)sizeof(UInt32);
|
|
|
|
if (frame->interlace == INTERLACE_ODD) {
|
|
pDst1 += dstPitch;
|
|
height--;
|
|
}
|
|
|
|
for (h = 0; h < height; h++) {
|
|
UInt16* pSrc = frame->line[h].buffer;
|
|
UInt32 colCur = (rgbTable[pSrc[0]] & 0xf0f0f0) >> 4;
|
|
UInt32 colPrev2 = colCur;
|
|
UInt32 colPrev1 = colCur;
|
|
UInt32 colNext1 = colCur;
|
|
int dstIndex = 0;
|
|
|
|
if (frame->line[h].doubleWidth) {
|
|
int width = srcWidth * 2;
|
|
int w;
|
|
for (w = 0; w < width;) {
|
|
UInt32 colNext2;
|
|
UInt32 colRgb1;
|
|
UInt32 colRgb2;
|
|
UInt32 colLgt;
|
|
UInt32 noise;
|
|
|
|
colNext2 = (rgbTable[pSrc[w++]] & 0xf0f0f0) >> 4;
|
|
colLgt = colCur;
|
|
colRgb1 = (colPrev2 + colNext2 + 2 * colNext1 + 4 * colPrev1 + 8 * colLgt) & 0xf0f0f0;
|
|
|
|
colPrev2 = colPrev1;
|
|
colPrev1 = colCur;
|
|
colCur = colNext1;
|
|
colNext1 = colNext2;
|
|
colNext2 = pSrc[w];
|
|
|
|
colNext2 = (rgbTable[pSrc[w++]] & 0xf0f0f0) >> 4;
|
|
colLgt = colCur;
|
|
colRgb2 = (colPrev2 + colNext2 + 2 * colPrev1 + 4 * colNext1 + 8 * colLgt) & 0xf0f0f0;
|
|
|
|
colPrev2 = colPrev1;
|
|
colPrev1 = colCur;
|
|
colCur = colNext1;
|
|
colNext1 = colNext2;
|
|
|
|
noise = (rnd >> 29) * 0x10101;
|
|
pDst1[dstIndex++] = colRgb1 + noise;
|
|
pDst1[dstIndex++] = colRgb2 + noise;
|
|
|
|
rnd *= 23;
|
|
}
|
|
}
|
|
else {
|
|
int width = srcWidth;
|
|
int w;
|
|
for (w = 0; w < width;) {
|
|
UInt32 colNext;
|
|
UInt32 colRgb1;
|
|
UInt32 colRgb2;
|
|
UInt32 colLgt;
|
|
UInt32 noise;
|
|
|
|
colNext = (rgbTable[pSrc[w++]] & 0xf0f0f0) >> 4;
|
|
colLgt = colCur;
|
|
colRgb1 = (2 * colNext + 6 * colPrev1 + 8 * colLgt) & 0xf0f0f0;
|
|
colRgb2 = (2 * colPrev1 + 6 * colNext + 8 * colLgt) & 0xf0f0f0;
|
|
|
|
noise = (rnd >> 29) * 0x10101;
|
|
pDst1[dstIndex++] = colRgb1 + noise;
|
|
pDst1[dstIndex++] = colRgb2 + noise;
|
|
|
|
|
|
rnd *= 23;
|
|
colPrev1 = colCur;
|
|
colCur = colNext;
|
|
}
|
|
}
|
|
pDst1 += dstPitch;
|
|
}
|
|
}
|
|
|
|
static void copyPAL_1x1_16(FrameBuffer* frame, void* pDestination, int dstPitch, UInt16* rgbTable, UInt32 rnd)
|
|
{
|
|
static UInt32 rndVal = 51;
|
|
UInt16* pDst = (UInt16*)pDestination;
|
|
int height = frame->lines;
|
|
int srcWidth = frame->maxWidth;
|
|
int h;
|
|
|
|
rndVal *= 13;
|
|
rnd *= rndVal;
|
|
|
|
dstPitch /= (int)sizeof(UInt16);
|
|
|
|
for (h = 0; h < height; h++) {
|
|
UInt16* pSrc = frame->line[h].buffer;
|
|
UInt16 colCur = (rgbTable[pSrc[0]] & 0xe79c) >> 2;
|
|
UInt16 colPrev = colCur;
|
|
int dstIndex = 0;
|
|
int w;
|
|
|
|
if (frame->line[h].doubleWidth) {
|
|
int width = srcWidth * 2;
|
|
for (w = 0; w < width;) {
|
|
UInt16 colTmp1 = (rgbTable[pSrc[w++]] & 0xc718) >> 3;
|
|
UInt16 colTmp2 = (rgbTable[pSrc[w++]] & 0xc718) >> 3;
|
|
UInt16 colNext = (colTmp1 + colTmp2) & 0xe79c;
|
|
UInt16 colRgb = (colPrev + 2 * colCur + colNext) & 0xe79c;
|
|
|
|
colPrev = colCur;
|
|
colCur = colNext;
|
|
|
|
pDst[dstIndex++] = colRgb + (UInt16)(rnd >> 31) * 0x0821;
|
|
rnd *= 23;
|
|
}
|
|
}
|
|
else {
|
|
int width = srcWidth;
|
|
for (w = 0; w < width;) {
|
|
UInt16 colNext = (rgbTable[pSrc[w++]] & 0xe79c) >> 2;
|
|
UInt16 colRgb = (colPrev + 2 * colCur + colNext) & 0xe79c;
|
|
colPrev = colCur;
|
|
colCur = colNext;
|
|
|
|
pDst[dstIndex++] = colRgb + (UInt16)(rnd >> 31) * 0x0821;
|
|
rnd *= 23;
|
|
}
|
|
}
|
|
pDst += dstPitch;
|
|
}
|
|
}
|
|
|
|
|
|
static void copyPAL_1x1_32(FrameBuffer* frame, void* pDestination, int dstPitch, UInt32* rgbTable, UInt32 rnd)
|
|
{
|
|
static UInt32 rndVal = 51;
|
|
UInt32* pDst = (UInt32*)pDestination;
|
|
int height = frame->lines;
|
|
int srcWidth = frame->maxWidth;
|
|
int h;
|
|
|
|
rndVal *= 13;
|
|
rnd *= rndVal;
|
|
|
|
dstPitch /= (int)sizeof(UInt32);
|
|
|
|
for (h = 0; h < height; h++) {
|
|
UInt16* pSrc = frame->line[h].buffer;
|
|
UInt32 colCur = (rgbTable[pSrc[0]] & 0xfcfcfc) >> 2;
|
|
UInt32 colPrev = colCur;
|
|
int dstIndex = 0;
|
|
int w;
|
|
|
|
if (frame->line[h].doubleWidth) {
|
|
int width = srcWidth * 2;
|
|
for (w = 0; w < width; ) {
|
|
UInt32 colTmp1 = (rgbTable[pSrc[w++]] & 0xf8f8f8) >> 3;
|
|
UInt32 colTmp2 = (rgbTable[pSrc[w++]] & 0xf8f8f8) >> 3;
|
|
UInt32 colNext = (colTmp1 + colTmp2) & 0xfcfcfc;
|
|
UInt32 colRgb = (colPrev + 2 * colCur + colNext) & 0xfcfcfc;
|
|
|
|
colPrev = colCur;
|
|
colCur = colNext;
|
|
|
|
pDst[dstIndex++] = colRgb + (rnd >> 31) * 0x10101;
|
|
rnd *= 23;
|
|
}
|
|
}
|
|
else {
|
|
int width = srcWidth;
|
|
for (w = 0; w < width;) {
|
|
UInt32 colNext = (rgbTable[pSrc[w++]] & 0xfcfcfc) >> 2;
|
|
UInt32 colRgb = (colPrev + 2 * colCur + colNext) & 0xfcfcfc;
|
|
colPrev = colCur;
|
|
colCur = colNext;
|
|
|
|
pDst[dstIndex++] = colRgb + (rnd >> 31) * 0x10101;
|
|
rnd *= 23;
|
|
}
|
|
}
|
|
pDst += dstPitch;
|
|
}
|
|
}
|
|
|
|
static void copyPAL_1x05_32(FrameBuffer* frame, void* pDestination, int dstPitch, UInt32* rgbTable, UInt32 rnd)
|
|
{
|
|
static UInt32 rndVal = 51;
|
|
UInt32* pDst = (UInt32*)pDestination;
|
|
int height = frame->lines;
|
|
int srcWidth = frame->maxWidth;
|
|
int h;
|
|
|
|
rndVal *= 13;
|
|
rnd *= rndVal;
|
|
|
|
dstPitch /= (int)sizeof(UInt32);
|
|
|
|
for (h = 0; h < height; h += 2) {
|
|
UInt16* pSrcA = frame->line[h + 0].buffer;
|
|
UInt16* pSrcB = frame->line[h + 1].buffer;
|
|
UInt32 colCur = (rgbTable[pSrcA[0]] & 0xfcfcfc) >> 2;
|
|
UInt32 colPrev = colCur;
|
|
int dstIndex = 0;
|
|
int w;
|
|
|
|
if (frame->line[h].doubleWidth) {
|
|
int width = srcWidth * 2;
|
|
for (w = 0; w < width;) {
|
|
UInt32 colTmp1A = (rgbTable[pSrcA[w ]] & 0xf0f0f0) >> 4;
|
|
UInt32 colTmp1B = (rgbTable[pSrcB[w++]] & 0xf0f0f0) >> 4;
|
|
UInt32 colTmp2A = (rgbTable[pSrcA[w ]] & 0xf0f0f0) >> 4;
|
|
UInt32 colTmp2B = (rgbTable[pSrcB[w++]] & 0xf0f0f0) >> 4;
|
|
UInt32 colNext = (colTmp1A + colTmp2A + colTmp1B + colTmp2B) & 0xf0f0f0;
|
|
UInt32 colRgb = (colPrev + 2 * colCur + colNext) & 0xfcfcfc;
|
|
|
|
colPrev = colCur;
|
|
colCur = colNext;
|
|
|
|
pDst[dstIndex++] = colRgb + (rnd >> 31) * 0x10101;
|
|
rnd *= 23;
|
|
}
|
|
}
|
|
else {
|
|
int width = srcWidth;
|
|
for (w = 0; w < width;) {
|
|
UInt32 colTmpA = (rgbTable[pSrcA[w ]] & 0xf8f8f8) >> 3;
|
|
UInt32 colTmpB = (rgbTable[pSrcB[w++]] & 0xf8f8f8) >> 3;
|
|
UInt32 colNext = (colTmpA + colTmpB) & 0xf8f8f8;
|
|
UInt32 colRgb = (colPrev + 2 * colCur + colNext) & 0xfcfcfc;
|
|
|
|
colPrev = colCur;
|
|
colCur = colNext;
|
|
|
|
pDst[dstIndex++] = colRgb + (rnd >> 31) * 0x10101;
|
|
rnd *= 23;
|
|
}
|
|
}
|
|
pDst += dstPitch;
|
|
}
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
**
|
|
** Fast rendering routines
|
|
**
|
|
******************************************************************************
|
|
*/
|
|
static void copy_1x1_16(FrameBuffer* frame, void* pDestination, int dstPitch, UInt16* rgbTable)
|
|
{
|
|
UInt16* pDst = (UInt16*)pDestination;
|
|
int height = frame->lines;
|
|
int srcWidth = frame->maxWidth;
|
|
int h;
|
|
|
|
dstPitch /= (int)sizeof(UInt16);
|
|
|
|
for (h = 0; h < height; h++) {
|
|
UInt16* pOldDst = pDst;
|
|
UInt16* pSrc = frame->line[h].buffer;
|
|
|
|
if (frame->line[h].doubleWidth) {
|
|
int width = srcWidth / 4;
|
|
while (width--) {
|
|
pDst[0] = (((rgbTable[pSrc[0]] & 0xe79c) >> 1) + ((rgbTable[pSrc[1]] & 0xe79c) >> 1)) & 0xe79c;
|
|
pDst[1] = (((rgbTable[pSrc[2]] & 0xe79c) >> 1) + ((rgbTable[pSrc[3]] & 0xe79c) >> 1)) & 0xe79c;
|
|
pDst[2] = (((rgbTable[pSrc[4]] & 0xe79c) >> 1) + ((rgbTable[pSrc[5]] & 0xe79c) >> 1)) & 0xe79c;
|
|
pDst[3] = (((rgbTable[pSrc[6]] & 0xe79c) >> 1) + ((rgbTable[pSrc[7]] & 0xe79c) >> 1)) & 0xe79c;
|
|
pSrc += 8;
|
|
pDst += 4;
|
|
}
|
|
}
|
|
else {
|
|
int width = srcWidth / 4;
|
|
while (width--) {
|
|
pDst[0] = rgbTable[pSrc[0]];
|
|
pDst[1] = rgbTable[pSrc[1]];
|
|
pDst[2] = rgbTable[pSrc[2]];
|
|
pDst[3] = rgbTable[pSrc[3]];
|
|
pSrc += 4;
|
|
pDst += 4;
|
|
}
|
|
}
|
|
pDst = pOldDst + dstPitch;
|
|
}
|
|
}
|
|
|
|
|
|
static void copy_1x1_32(FrameBuffer* frame, void* pDestination, int dstPitch, UInt32* rgbTable)
|
|
{
|
|
UInt32* pDst = (UInt32*)pDestination;
|
|
int height = frame->lines;
|
|
int srcWidth = frame->maxWidth;
|
|
int h;
|
|
|
|
dstPitch /= (int)sizeof(UInt32);
|
|
|
|
for (h = 0; h < height; h++) {
|
|
UInt32* pOldDst = pDst;
|
|
UInt16* pSrc = frame->line[h].buffer;
|
|
|
|
if (frame->line[h].doubleWidth) {
|
|
int width = srcWidth / 4;
|
|
while (width--) {
|
|
pDst[0] = (((rgbTable[pSrc[0]] & 0xfefefe) >> 1) + ((rgbTable[pSrc[1]] & 0xfefefe) >> 1)) & 0xfefefe;
|
|
pDst[1] = (((rgbTable[pSrc[2]] & 0xfefefe) >> 1) + ((rgbTable[pSrc[3]] & 0xfefefe) >> 1)) & 0xfefefe;
|
|
pDst[2] = (((rgbTable[pSrc[4]] & 0xfefefe) >> 1) + ((rgbTable[pSrc[5]] & 0xfefefe) >> 1)) & 0xfefefe;
|
|
pDst[3] = (((rgbTable[pSrc[6]] & 0xfefefe) >> 1) + ((rgbTable[pSrc[7]] & 0xfefefe) >> 1)) & 0xfefefe;
|
|
pSrc += 8;
|
|
pDst += 4;
|
|
}
|
|
}
|
|
else {
|
|
int width = srcWidth / 4;
|
|
while (width--) {
|
|
pDst[0] = rgbTable[pSrc[0]];
|
|
pDst[1] = rgbTable[pSrc[1]];
|
|
pDst[2] = rgbTable[pSrc[2]];
|
|
pDst[3] = rgbTable[pSrc[3]];
|
|
pSrc += 4;
|
|
pDst += 4;
|
|
}
|
|
}
|
|
pDst = pOldDst + dstPitch;
|
|
}
|
|
}
|
|
|
|
static void copy_1x05_16(FrameBuffer* frame, void* pDestination, int dstPitch, UInt16* rgbTable)
|
|
{
|
|
UInt16* pDst = (UInt16*)pDestination;
|
|
int height = frame->lines;
|
|
int srcWidth = frame->maxWidth;
|
|
int h;
|
|
|
|
dstPitch /= (int)sizeof(UInt16);
|
|
|
|
for (h = 0; h < height; h += 2) {
|
|
UInt16* pOldDst = pDst;
|
|
UInt16* pSrc1 = frame->line[h + 0].buffer;
|
|
UInt16* pSrc2 = frame->line[h + 1].buffer;
|
|
|
|
if (frame->line[h].doubleWidth) {
|
|
int width = srcWidth;
|
|
while (width--) {
|
|
UInt16 col0 = (((rgbTable[pSrc1[0]] & 0xe79c) >> 2) + ((rgbTable[pSrc1[1]] & 0xe79c) >> 2));
|
|
UInt16 col1 = (((rgbTable[pSrc2[0]] & 0xe79c) >> 2) + ((rgbTable[pSrc2[1]] & 0xe79c) >> 2));
|
|
|
|
*pDst++ = (col0 + col1) & 0xe79c;
|
|
pSrc1 += 2;
|
|
pSrc2 += 2;
|
|
}
|
|
}
|
|
else {
|
|
int width = srcWidth;
|
|
while (width--) {
|
|
*pDst++ = (((rgbTable[pSrc1[0]] & 0xe79c) >> 1) + ((rgbTable[pSrc2[0]] & 0xe79c) >> 1)) & 0xe79c;
|
|
}
|
|
}
|
|
pDst = pOldDst + dstPitch;
|
|
}
|
|
}
|
|
|
|
|
|
static void copy_1x05_32(FrameBuffer* frame, void* pDestination, int dstPitch, UInt32* rgbTable)
|
|
{
|
|
UInt32* pDst = (UInt32*)pDestination;
|
|
int height = frame->lines;
|
|
int srcWidth = frame->maxWidth;
|
|
int h;
|
|
|
|
dstPitch /= (int)sizeof(UInt32);
|
|
|
|
for (h = 0; h < height; h += 2) {
|
|
UInt32* pOldDst = pDst;
|
|
UInt16* pSrc1 = frame->line[h + 0].buffer;
|
|
UInt16* pSrc2 = frame->line[h + 1].buffer;
|
|
|
|
if (frame->line[h].doubleWidth) {
|
|
int width = srcWidth;
|
|
while (width--) {
|
|
UInt32 col0 = (((rgbTable[pSrc1[0]] & 0xfcfcfc) >> 2) + ((rgbTable[pSrc1[1]] & 0xfcfcfc) >> 2));
|
|
UInt32 col1 = (((rgbTable[pSrc2[0]] & 0xfcfcfc) >> 2) + ((rgbTable[pSrc2[1]] & 0xfcfcfc) >> 2));
|
|
|
|
*pDst++ = (col0 + col1) & 0xfcfcfc;
|
|
pSrc1 += 2;
|
|
pSrc2 += 2;
|
|
}
|
|
}
|
|
else {
|
|
int width = srcWidth;
|
|
while (width--) {
|
|
*pDst++ = (((rgbTable[pSrc1[0]] & 0xfefefe) >> 1) + ((rgbTable[pSrc2[0]] & 0xfefefe) >> 1)) & 0xfefefe;
|
|
pSrc1++;
|
|
pSrc2++;
|
|
}
|
|
}
|
|
pDst = pOldDst + dstPitch;
|
|
}
|
|
}
|
|
|
|
|
|
static void copy_2x2_16(FrameBuffer* frame, void* pDestination, int dstPitch, UInt16* rgbTable)
|
|
{
|
|
UInt16* pDst1 = (UInt16*)pDestination;
|
|
UInt16* pDst2 = pDst1 + dstPitch / (int)sizeof(UInt16);
|
|
int height = frame->lines;
|
|
int srcWidth = frame->maxWidth;
|
|
int h;
|
|
|
|
dstPitch /= (int)sizeof(UInt16);
|
|
|
|
if (frame->interlace == INTERLACE_ODD) {
|
|
pDst1 += dstPitch;
|
|
pDst2 += dstPitch;
|
|
height--;
|
|
}
|
|
|
|
for (h = 0; h < height; h++) {
|
|
UInt16* pDst1old = pDst1;
|
|
UInt16* pDst2old = pDst2;
|
|
UInt16* pSrc = frame->line[h].buffer;
|
|
|
|
if (frame->line[h].doubleWidth) {
|
|
int width = srcWidth / 4 * 2;
|
|
while (width--) {
|
|
UInt16 col1 = rgbTable[pSrc[0]];
|
|
UInt16 col2 = rgbTable[pSrc[1]];
|
|
UInt16 col3 = rgbTable[pSrc[2]];
|
|
UInt16 col4 = rgbTable[pSrc[3]];
|
|
pSrc += 4;
|
|
|
|
pDst1[0] = col1;
|
|
pDst1[1] = col2;
|
|
pDst1[2] = col3;
|
|
pDst1[3] = col4;
|
|
pDst1 += 4;
|
|
|
|
pDst2[0] = col1;
|
|
pDst2[1] = col2;
|
|
pDst2[2] = col3;
|
|
pDst2[3] = col4;
|
|
pDst2 += 4;
|
|
}
|
|
}
|
|
else {
|
|
int width = srcWidth / 4;
|
|
while (width--) {
|
|
UInt16 col1 = rgbTable[pSrc[0]];
|
|
UInt16 col2 = rgbTable[pSrc[1]];
|
|
UInt16 col3 = rgbTable[pSrc[2]];
|
|
UInt16 col4 = rgbTable[pSrc[3]];
|
|
pSrc += 4;
|
|
|
|
pDst1[0] = col1;
|
|
pDst1[1] = col1;
|
|
pDst1[2] = col2;
|
|
pDst1[3] = col2;
|
|
pDst1[4] = col3;
|
|
pDst1[5] = col3;
|
|
pDst1[6] = col4;
|
|
pDst1[7] = col4;
|
|
pDst1 += 8;
|
|
|
|
pDst2[0] = col1;
|
|
pDst2[1] = col1;
|
|
pDst2[2] = col2;
|
|
pDst2[3] = col2;
|
|
pDst2[4] = col3;
|
|
pDst2[5] = col3;
|
|
pDst2[6] = col4;
|
|
pDst2[7] = col4;
|
|
pDst2 += 8;
|
|
}
|
|
}
|
|
|
|
pDst1 = pDst1old + dstPitch * 2;
|
|
pDst2 = pDst2old + dstPitch * 2;
|
|
}
|
|
}
|
|
|
|
#ifndef NO_ASM
|
|
/* 7500 units -> 4100 units */
|
|
static void copy_2x2_32_core1_SSE(UInt32* rgbTable, UInt16* pSrc, UInt32* pDst1, UInt32* pDst2, int width, int hint) {
|
|
|
|
#ifdef __GNUC__
|
|
__asm__(
|
|
"movl $0,%%esi \n\t"
|
|
"movl %4,%%ecx \n\t" // width
|
|
"movl %1,%%eax \n\t" // pSrc
|
|
"movl %2,%%ebx \n\t" // pDst1
|
|
"movl %0,%%edi \n\t" // rgbTable
|
|
"inner_loop1: \n\t"
|
|
"movw (%%eax),%%si \n\t"
|
|
"movd (%%edi,%%esi,4),%%mm0 \n\t"
|
|
"movw 2(%%eax),%%si \n\t"
|
|
"movd (%%edi,%%esi,4),%%mm1 \n\t"
|
|
"movw 6(%%eax),%%si \n\t"
|
|
"punpckldq %%mm1,%%mm0 \n\t"
|
|
"movd (%%edi,%%esi,4),%%mm3 \n\t"
|
|
"movw 4(%%eax),%%si \n\t"
|
|
"movntq %%mm0,0(%%ebx) \n\t"
|
|
"addl $8,%%eax \n\t"
|
|
"movd (%%edi,%%esi,4),%%mm2 \n\t"
|
|
"addl $16,%%ebx \n\t"
|
|
"punpckldq %%mm3,%%mm2 \n\t"
|
|
"decl %%ecx \n\t"
|
|
"movntq %%mm2,-8(%%ebx) \n\t"
|
|
"jnz inner_loop1 \n\t"
|
|
|
|
//#-- second line
|
|
|
|
"movl %4,%%ecx \n\t" // width
|
|
"movl %1,%%eax \n\t" // pSrc
|
|
"movl %5,%%ebx \n\t" // hint
|
|
"movl %3,%%edx \n\t" // pDst2
|
|
"movl %0,%%edi \n\t" // rgbTable
|
|
"inner_loop2: \n\t"
|
|
"movw (%%eax),%%si \n\t"
|
|
"movd (%%edi,%%esi,4),%%mm0 \n\t"
|
|
"movw 2(%%eax),%%si \n\t"
|
|
"movd (%%edi,%%esi,4),%%mm1 \n\t"
|
|
"movw 6(%%eax),%%si \n\t"
|
|
"punpckldq %%mm1,%%mm0 \n\t"
|
|
"movd (%%edi,%%esi,4),%%mm3 \n\t"
|
|
"movw 4(%%eax),%%si \n\t"
|
|
"prefetcht0 (%%eax,%%ebx) \n\t"
|
|
"movntq %%mm0,0(%%edx) \n\t"
|
|
"addl $8,%%eax \n\t"
|
|
"movd (%%edi,%%esi,4),%%mm2 \n\t"
|
|
"addl $16,%%edx \n\t"
|
|
"punpckldq %%mm3,%%mm2 \n\t"
|
|
"decl %%ecx \n\t"
|
|
"movntq %%mm2,-8(%%edx) \n\t"
|
|
"jnz inner_loop2 \n\t"
|
|
|
|
"emms \n\t"
|
|
:
|
|
: "m" (rgbTable), "m" (pSrc), "m" (pDst1), "m" (pDst2), "m" (width), "m" (hint)
|
|
: "%eax", "%ebx", "%ecx", "%edx", "%edi", "%esi"
|
|
);
|
|
#else
|
|
__asm{
|
|
mov esi,0
|
|
mov ecx,width
|
|
mov eax,pSrc
|
|
mov ebx,pDst1
|
|
mov edi,rgbTable
|
|
inner_loop1:
|
|
mov si,[eax]
|
|
movd mm0,[edi+esi*4]
|
|
mov si,[eax+2]
|
|
movd mm1,[edi+esi*4]
|
|
mov si,[eax+6]
|
|
punpckldq mm0,mm1
|
|
movd mm3,[edi+esi*4]
|
|
mov si,[eax+4]
|
|
movntq [ebx+0],mm0
|
|
add eax,8
|
|
movd mm2,[edi+esi*4]
|
|
add ebx,16
|
|
punpckldq mm2,mm3
|
|
dec ecx
|
|
movntq [ebx-8],mm2
|
|
jnz inner_loop1
|
|
|
|
;-- second line
|
|
|
|
mov ecx,width
|
|
mov eax,pSrc
|
|
mov ebx,hint
|
|
mov edx,pDst2
|
|
mov edi,rgbTable
|
|
inner_loop2:
|
|
mov si,[eax]
|
|
movd mm0,[edi+esi*4]
|
|
mov si,[eax+2]
|
|
movd mm1,[edi+esi*4]
|
|
mov si,[eax+6]
|
|
punpckldq mm0,mm1
|
|
movd mm3,[edi+esi*4]
|
|
mov si,[eax+4]
|
|
prefetcht0 [eax+ebx]
|
|
movntq [edx+0],mm0
|
|
add eax,8
|
|
movd mm2,[edi+esi*4]
|
|
add edx,16
|
|
punpckldq mm2,mm3
|
|
dec ecx
|
|
movntq [edx-8],mm2
|
|
jnz inner_loop2
|
|
|
|
emms
|
|
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
void copy_2x2_32_core1(UInt32* rgbTable, UInt16* pSrc, UInt32* pDst1, UInt32* pDst2, int width, int hint)
|
|
{
|
|
while (width--) {
|
|
UInt32 col1 = rgbTable[pSrc[0]];
|
|
UInt32 col2 = rgbTable[pSrc[1]];
|
|
UInt32 col3 = rgbTable[pSrc[2]];
|
|
UInt32 col4 = rgbTable[pSrc[3]];
|
|
pSrc += 4;
|
|
|
|
pDst1[0] = col1;
|
|
pDst1[1] = col2;
|
|
pDst1[2] = col3;
|
|
pDst1[3] = col4;
|
|
pDst1 += 4;
|
|
|
|
pDst2[0] = col1;
|
|
pDst2[1] = col2;
|
|
pDst2[2] = col3;
|
|
pDst2[3] = col4;
|
|
pDst2 += 4;
|
|
}
|
|
}
|
|
|
|
#ifndef NO_ASM
|
|
/* 6000 units -> 2500 units */
|
|
void copy_2x2_32_core2_SSE(UInt32* rgbTable, UInt16* pSrc, UInt32* pDst1, UInt32* pDst2, int width, int hint) {
|
|
|
|
#ifdef __GNUC__
|
|
__asm__(
|
|
"movl $0,%%esi \n\t"
|
|
"movl %4,%%ecx \n\t" // width
|
|
"movl %1,%%eax \n\t" // pSrc
|
|
"movl %2,%%ebx \n\t" // pDst1
|
|
"movl %0,%%edi \n\t" // rgbTable
|
|
"inner_loop3: \n\t"
|
|
"movw (%%eax),%%si \n\t"
|
|
"movd (%%edi,%%esi,4),%%mm0 \n\t"
|
|
"movw 2(%%eax),%%si \n\t"
|
|
"punpckldq %%mm0,%%mm0 \n\t"
|
|
"movd (%%edi,%%esi,4),%%mm1 \n\t"
|
|
"movntq %%mm0,0(%%ebx) \n\t"
|
|
|
|
"punpckldq %%mm1,%%mm1 \n\t"
|
|
"movw 4(%%eax),%%si \n\t"
|
|
"movntq %%mm1,8(%%ebx) \n\t"
|
|
|
|
"movd (%%edi,%%esi,4),%%mm0 \n\t"
|
|
"punpckldq %%mm0,%%mm0 \n\t"
|
|
"movw 6(%%eax),%%si \n\t"
|
|
"movntq %%mm0,16(%%ebx) \n\t"
|
|
|
|
"addl $32,%%ebx \n\t"
|
|
"movd (%%edi,%%esi,4),%%mm0 \n\t"
|
|
"addl $8,%%eax \n\t"
|
|
"punpckldq %%mm0,%%mm0 \n\t"
|
|
"decl %%ecx \n\t"
|
|
"movntq %%mm0,24-32(%%ebx) \n\t"
|
|
|
|
"jnz inner_loop3 \n\t"
|
|
|
|
//#-- second line
|
|
|
|
"movl %4,%%ecx \n\t" // width
|
|
"movl %1,%%eax \n\t" // pSrc
|
|
"movl %5,%%edx \n\t" // hint
|
|
"movl %3,%%ebx \n\t" // pDst2
|
|
"movl %0,%%edi \n\t" // rgbTable
|
|
"inner_loop4: \n\t"
|
|
"movw (%%eax),%%si \n\t"
|
|
"movd (%%edi,%%esi,4),%%mm0 \n\t"
|
|
"punpckldq %%mm0,%%mm0 \n\t"
|
|
"movw 2(%%eax),%%si \n\t"
|
|
"movntq %%mm0,0(%%ebx) \n\t"
|
|
|
|
"movd (%%edi,%%esi,4),%%mm0 \n\t"
|
|
"punpckldq %%mm0,%%mm0 \n\t"
|
|
"movw 4(%%eax),%%si \n\t"
|
|
"movntq %%mm0,8(%%ebx) \n\t"
|
|
|
|
"movd (%%edi,%%esi,4),%%mm0 \n\t"
|
|
"prefetcht0 (%%eax,%%edx) \n\t"
|
|
"punpckldq %%mm0,%%mm0 \n\t"
|
|
"movw 6(%%eax),%%si \n\t"
|
|
"movntq %%mm0,16(%%ebx) \n\t"
|
|
|
|
"addl $32,%%ebx \n\t"
|
|
"movd (%%edi,%%esi,4),%%mm0 \n\t"
|
|
"addl $8,%%eax \n\t"
|
|
"punpckldq %%mm0,%%mm0 \n\t"
|
|
"decl %%ecx \n\t"
|
|
"movntq %%mm0,24-32(%%ebx) \n\t"
|
|
|
|
"jnz inner_loop4 \n\t"
|
|
|
|
"emms \n\t"
|
|
:
|
|
: "m" (rgbTable), "m" (pSrc), "m" (pDst1), "m" (pDst2), "m" (width), "m" (hint)
|
|
: "%eax", "%ebx", "%ecx", "%edx", "%edi", "%esi"
|
|
);
|
|
#else
|
|
__asm{
|
|
mov esi,0
|
|
mov ecx,width
|
|
mov eax,pSrc
|
|
mov ebx,pDst1
|
|
mov edi,rgbTable
|
|
inner_loop1:
|
|
mov si,[eax]
|
|
movd mm0,[edi+esi*4]
|
|
mov si,[eax+2]
|
|
punpckldq mm0,mm0
|
|
movd mm1,[edi+esi*4]
|
|
movntq [ebx+0],mm0
|
|
|
|
punpckldq mm1,mm1
|
|
mov si,[eax+4]
|
|
movntq [ebx+8],mm1
|
|
|
|
movd mm0,[edi+esi*4]
|
|
punpckldq mm0,mm0
|
|
mov si,[eax+6]
|
|
movntq [ebx+16],mm0
|
|
|
|
add ebx,32
|
|
movd mm0,[edi+esi*4]
|
|
add eax,8
|
|
punpckldq mm0,mm0
|
|
dec ecx
|
|
movntq [ebx+24-32],mm0
|
|
|
|
jnz inner_loop1
|
|
|
|
;-- second line
|
|
|
|
mov ecx,width
|
|
mov eax,pSrc
|
|
mov edx,hint
|
|
mov ebx,pDst2
|
|
mov edi,rgbTable
|
|
inner_loop2:
|
|
mov si,[eax]
|
|
movd mm0,[edi+esi*4]
|
|
punpckldq mm0,mm0
|
|
mov si,[eax+2]
|
|
movntq [ebx+0],mm0
|
|
|
|
movd mm0,[edi+esi*4]
|
|
punpckldq mm0,mm0
|
|
mov si,[eax+4]
|
|
movntq [ebx+8],mm0
|
|
|
|
movd mm0,[edi+esi*4]
|
|
prefetcht0 [eax+edx]
|
|
punpckldq mm0,mm0
|
|
mov si,[eax+6]
|
|
movntq [ebx+16],mm0
|
|
|
|
add ebx,32
|
|
movd mm0,[edi+esi*4]
|
|
add eax,8
|
|
punpckldq mm0,mm0
|
|
dec ecx
|
|
movntq [ebx+24-32],mm0
|
|
|
|
jnz inner_loop2
|
|
|
|
emms
|
|
|
|
}
|
|
#endif
|
|
|
|
}
|
|
#endif
|
|
|
|
void copy_2x2_32_core2(UInt32* rgbTable, UInt16* pSrc, UInt32* pDst1, UInt32* pDst2, int width, int hint) {
|
|
|
|
while (width--) {
|
|
UInt32 col1 = rgbTable[pSrc[0]];
|
|
UInt32 col2 = rgbTable[pSrc[1]];
|
|
UInt32 col3 = rgbTable[pSrc[2]];
|
|
UInt32 col4 = rgbTable[pSrc[3]];
|
|
pSrc += 4;
|
|
|
|
pDst1[0] = col1;
|
|
pDst1[1] = col1;
|
|
pDst1[2] = col2;
|
|
pDst1[3] = col2;
|
|
pDst1[4] = col3;
|
|
pDst1[5] = col3;
|
|
pDst1[6] = col4;
|
|
pDst1[7] = col4;
|
|
pDst1 += 8;
|
|
|
|
pDst2[0] = col1;
|
|
pDst2[1] = col1;
|
|
pDst2[2] = col2;
|
|
pDst2[3] = col2;
|
|
pDst2[4] = col3;
|
|
pDst2[5] = col3;
|
|
pDst2[6] = col4;
|
|
pDst2[7] = col4;
|
|
pDst2 += 8;
|
|
}
|
|
}
|
|
|
|
static void copy_2x2_32(FrameBuffer* frame, void* pDestination, int dstPitch, UInt32* rgbTable)
|
|
{
|
|
UInt32* pDst1 = (UInt32*)pDestination;
|
|
UInt32* pDst2 = pDst1 + dstPitch / (int)sizeof(UInt32);
|
|
int height = frame->lines;
|
|
int srcWidth = frame->maxWidth;
|
|
int h;
|
|
void (*core1) (UInt32*, UInt16*, UInt32*, UInt32* , int , int );
|
|
void (*core2) (UInt32*, UInt16*, UInt32*, UInt32* , int , int );
|
|
#ifndef NO_ASM
|
|
int hasSSE=0;
|
|
const int SSEbit=1<<25;
|
|
|
|
#ifdef __GNUC__
|
|
__asm__ (
|
|
"movl $1,%%eax \n\t"
|
|
"cpuid \n\t"
|
|
"andl $0x2000000,%%edx \n\t"
|
|
"movl %%edx,%0 \n\t"
|
|
: "=r" (hasSSE) : : "%eax", "%ebx", "%ecx", "%edx"
|
|
);
|
|
#else
|
|
__asm {
|
|
mov eax,1
|
|
cpuid
|
|
and edx,SSEbit
|
|
mov hasSSE,edx
|
|
}
|
|
#endif
|
|
|
|
hasSSE = 1;
|
|
core1=hasSSE? copy_2x2_32_core1_SSE: copy_2x2_32_core1;
|
|
core2=hasSSE? copy_2x2_32_core2_SSE: copy_2x2_32_core2;
|
|
#else
|
|
core1=copy_2x2_32_core1;
|
|
core2=copy_2x2_32_core2;
|
|
#endif
|
|
|
|
/*rdtsc_start_timer(0);*/
|
|
dstPitch /= (int)sizeof(UInt32);
|
|
|
|
if (frame->interlace == INTERLACE_ODD) {
|
|
pDst1 += dstPitch;
|
|
pDst2 += dstPitch;
|
|
height--;
|
|
}
|
|
|
|
for (h = 0; h < height; h++) {
|
|
|
|
if (frame->line[h].doubleWidth)
|
|
core1(rgbTable,frame->line[h].buffer,pDst1,pDst2,srcWidth / 4 * 2,dstPitch * 2*4);
|
|
else
|
|
core2(rgbTable,frame->line[h].buffer,pDst1,pDst2,srcWidth / 4,dstPitch * 2*4);
|
|
|
|
pDst1 += dstPitch * 2;
|
|
pDst2 += dstPitch * 2;
|
|
}
|
|
/*rdtsc_end_timer(0);*/
|
|
}
|
|
|
|
static void copy_2x1_16(FrameBuffer* frame, void* pDestination, int dstPitch, UInt16* rgbTable)
|
|
{
|
|
UInt16* pDst1 = (UInt16*)pDestination;
|
|
int height = frame->lines;
|
|
int srcWidth = frame->maxWidth;
|
|
int h;
|
|
|
|
dstPitch /= (int)sizeof(UInt16);
|
|
|
|
if (frame->interlace == INTERLACE_ODD) {
|
|
pDst1 += dstPitch;
|
|
height--;
|
|
}
|
|
|
|
for (h = 0; h < height; h++) {
|
|
UInt16* pDst1old = pDst1;
|
|
UInt16* pSrc = frame->line[h].buffer;
|
|
|
|
if (frame->line[h].doubleWidth) {
|
|
int width = srcWidth / 4 * 2;
|
|
while (width--) {
|
|
pDst1[0] = rgbTable[pSrc[0]];
|
|
pDst1[1] = rgbTable[pSrc[1]];
|
|
pDst1[2] = rgbTable[pSrc[2]];
|
|
pDst1[3] = rgbTable[pSrc[3]];
|
|
pDst1 += 4;
|
|
pSrc += 4;
|
|
}
|
|
}
|
|
else {
|
|
int width = srcWidth / 4;
|
|
while (width--) {
|
|
UInt16 col1 = rgbTable[pSrc[0]];
|
|
UInt16 col2 = rgbTable[pSrc[1]];
|
|
UInt16 col3 = rgbTable[pSrc[2]];
|
|
UInt16 col4 = rgbTable[pSrc[3]];
|
|
pSrc += 4;
|
|
|
|
pDst1[0] = col1;
|
|
pDst1[1] = col1;
|
|
pDst1[2] = col2;
|
|
pDst1[3] = col2;
|
|
pDst1[4] = col3;
|
|
pDst1[5] = col3;
|
|
pDst1[6] = col4;
|
|
pDst1[7] = col4;
|
|
pDst1 += 8;
|
|
}
|
|
}
|
|
|
|
pDst1 = pDst1old + dstPitch;
|
|
}
|
|
}
|
|
|
|
static void copy_2x1_32(FrameBuffer* frame, void* pDestination, int dstPitch, UInt32* rgbTable)
|
|
{
|
|
UInt32* pDst1 = (UInt32*)pDestination;
|
|
int height = frame->lines;
|
|
int srcWidth = frame->maxWidth;
|
|
int h;
|
|
|
|
dstPitch /= (int)sizeof(UInt32);
|
|
|
|
if (frame->interlace == INTERLACE_ODD) {
|
|
pDst1 += dstPitch;
|
|
height--;
|
|
}
|
|
|
|
for (h = 0; h < height; h++) {
|
|
UInt32* pDst1old = pDst1;
|
|
UInt16* pSrc = frame->line[h].buffer;
|
|
|
|
if (frame->line[h].doubleWidth) {
|
|
int width = srcWidth / 4 * 2;
|
|
while (width--) {
|
|
pDst1[0] = rgbTable[pSrc[0]];
|
|
pDst1[1] = rgbTable[pSrc[1]];
|
|
pDst1[2] = rgbTable[pSrc[2]];
|
|
pDst1[3] = rgbTable[pSrc[3]];
|
|
pDst1 += 4;
|
|
pSrc += 4;
|
|
}
|
|
}
|
|
else {
|
|
int width = srcWidth / 4;
|
|
while (width--) {
|
|
UInt32 col1 = rgbTable[pSrc[0]];
|
|
UInt32 col2 = rgbTable[pSrc[1]];
|
|
UInt32 col3 = rgbTable[pSrc[2]];
|
|
UInt32 col4 = rgbTable[pSrc[3]];
|
|
pSrc += 4;
|
|
|
|
pDst1[0] = col1;
|
|
pDst1[1] = col1;
|
|
pDst1[2] = col2;
|
|
pDst1[3] = col2;
|
|
pDst1[4] = col3;
|
|
pDst1[5] = col3;
|
|
pDst1[6] = col4;
|
|
pDst1[7] = col4;
|
|
pDst1 += 8;
|
|
}
|
|
}
|
|
|
|
pDst1 = pDst1old + dstPitch;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
static void hq2x_2x2_32(FrameBuffer* frame, void* pDestination, int dstPitch, UInt16* rgbTable)
|
|
{
|
|
UInt16 ImgSrc[320 * 240];
|
|
UInt16* pDst = (UInt16*)ImgSrc;
|
|
int srcHeight = frame->lines;
|
|
int srcWidth = frame->maxWidth;
|
|
int h;
|
|
|
|
if (srcWidth == 0) {
|
|
return;
|
|
}
|
|
|
|
for (h = 0; h < srcHeight; h++) {
|
|
UInt16* pSrc = frame->line[h].buffer;
|
|
int width = srcWidth / 8;
|
|
while (width--) {
|
|
pDst[0] = rgbTable[pSrc[0]];
|
|
pDst[1] = rgbTable[pSrc[1]];
|
|
pDst[2] = rgbTable[pSrc[2]];
|
|
pDst[3] = rgbTable[pSrc[3]];
|
|
pDst[4] = rgbTable[pSrc[4]];
|
|
pDst[5] = rgbTable[pSrc[5]];
|
|
pDst[6] = rgbTable[pSrc[6]];
|
|
pDst[7] = rgbTable[pSrc[7]];
|
|
pSrc += 8;
|
|
pDst += 8;
|
|
}
|
|
}
|
|
|
|
hq2x_32(ImgSrc, pDestination, srcWidth, srcHeight, dstPitch);
|
|
}
|
|
|
|
static void hq3x_2x2_32(FrameBuffer* frame, void* pDestination, int dstPitch, UInt16* rgbTable)
|
|
{
|
|
UInt16 ImgSrc[320 * 240];
|
|
UInt16* pDst = (UInt16*)ImgSrc;
|
|
int srcHeight = frame->lines;
|
|
int srcWidth = frame->maxWidth;
|
|
int h;
|
|
|
|
if (srcWidth == 0) {
|
|
return;
|
|
}
|
|
|
|
for (h = 0; h < srcHeight; h++) {
|
|
UInt16* pSrc = frame->line[h].buffer;
|
|
int width = srcWidth / 8;
|
|
while (width--) {
|
|
pDst[0] = rgbTable[pSrc[0]];
|
|
pDst[1] = rgbTable[pSrc[1]];
|
|
pDst[2] = rgbTable[pSrc[2]];
|
|
pDst[3] = rgbTable[pSrc[3]];
|
|
pDst[4] = rgbTable[pSrc[4]];
|
|
pDst[5] = rgbTable[pSrc[5]];
|
|
pDst[6] = rgbTable[pSrc[6]];
|
|
pDst[7] = rgbTable[pSrc[7]];
|
|
pSrc += 8;
|
|
pDst += 8;
|
|
}
|
|
}
|
|
|
|
hq3x_32(ImgSrc, pDestination, srcWidth, srcHeight, dstPitch);
|
|
}
|
|
|
|
static void scale2x_2x2_32(FrameBuffer* frame, void* pDestination, int dstPitch, UInt32* rgbTable)
|
|
{
|
|
UInt32 ImgSrc[320 * 240];
|
|
UInt32* pDst = (UInt32*)ImgSrc;
|
|
int srcHeight = frame->lines;
|
|
int srcWidth = frame->maxWidth;
|
|
int h;
|
|
|
|
if (srcWidth == 0) {
|
|
return;
|
|
}
|
|
|
|
for (h = 0; h < srcHeight; h++) {
|
|
UInt16* pSrc = frame->line[h].buffer;
|
|
int width = srcWidth / 8;
|
|
while (width--) {
|
|
pDst[0] = rgbTable[pSrc[0]];
|
|
pDst[1] = rgbTable[pSrc[1]];
|
|
pDst[2] = rgbTable[pSrc[2]];
|
|
pDst[3] = rgbTable[pSrc[3]];
|
|
pDst[4] = rgbTable[pSrc[4]];
|
|
pDst[5] = rgbTable[pSrc[5]];
|
|
pDst[6] = rgbTable[pSrc[6]];
|
|
pDst[7] = rgbTable[pSrc[7]];
|
|
pSrc += 8;
|
|
pDst += 8;
|
|
}
|
|
}
|
|
|
|
scale(2, pDestination, dstPitch, ImgSrc, srcWidth * sizeof(UInt32), sizeof(UInt32), srcWidth, srcHeight);
|
|
}
|
|
|
|
static void scale2x_2x2_16(FrameBuffer* frame, void* pDestination, int dstPitch, UInt16* rgbTable)
|
|
{
|
|
UInt16 ImgSrc[320 * 240];
|
|
UInt16* pDst = (UInt16*)ImgSrc;
|
|
int srcHeight = frame->lines;
|
|
int srcWidth = frame->maxWidth;
|
|
int h;
|
|
|
|
if (srcWidth == 0) {
|
|
return;
|
|
}
|
|
|
|
for (h = 0; h < srcHeight; h++) {
|
|
UInt16* pSrc = frame->line[h].buffer;
|
|
int width = srcWidth / 8;
|
|
while (width--) {
|
|
pDst[0] = rgbTable[pSrc[0]];
|
|
pDst[1] = rgbTable[pSrc[1]];
|
|
pDst[2] = rgbTable[pSrc[2]];
|
|
pDst[3] = rgbTable[pSrc[3]];
|
|
pDst[4] = rgbTable[pSrc[4]];
|
|
pDst[5] = rgbTable[pSrc[5]];
|
|
pDst[6] = rgbTable[pSrc[6]];
|
|
pDst[7] = rgbTable[pSrc[7]];
|
|
pSrc += 8;
|
|
pDst += 8;
|
|
}
|
|
}
|
|
|
|
scale(2, pDestination, dstPitch, ImgSrc, srcWidth * sizeof(UInt16), sizeof(UInt16), srcWidth, srcHeight);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
**
|
|
** Public interface methods
|
|
**
|
|
******************************************************************************
|
|
*/
|
|
Video* videoCreate()
|
|
{
|
|
Video* pVideo = (Video*)calloc(1, sizeof(Video));
|
|
|
|
pVideo->gamma = 1;
|
|
pVideo->saturation = 1;
|
|
pVideo->brightness = 0;
|
|
pVideo->contrast = 1;
|
|
pVideo->deInterlace = 0;
|
|
pVideo->invertRGB = 0;
|
|
|
|
initRGBTable(pVideo);
|
|
|
|
hq2x_init();
|
|
hq3x_init();
|
|
|
|
pVideo->palMode = VIDEO_PAL_FAST;
|
|
pVideo->pRgbTable16 = pRgbTableColor16;
|
|
pVideo->pRgbTable32 = pRgbTableColor32;
|
|
|
|
return pVideo;
|
|
}
|
|
|
|
Video *videoCopy(const Video *original)
|
|
{
|
|
Video* pVideo = (Video*)calloc(1, sizeof(Video));
|
|
|
|
if (!pVideo)
|
|
return NULL;
|
|
|
|
pVideo->palMode = original->palMode;
|
|
pVideo->scanLinesEnable = original->scanLinesEnable;
|
|
pVideo->scanLinesPct = original->scanLinesPct;
|
|
pVideo->colorSaturationEnable = original->colorSaturationEnable;
|
|
pVideo->colorSaturationWidth = original->colorSaturationWidth;
|
|
pVideo->gamma = original->gamma;
|
|
pVideo->saturation = original->saturation;
|
|
pVideo->brightness = original->brightness;
|
|
pVideo->contrast = original->contrast;
|
|
pVideo->deInterlace = original->deInterlace;
|
|
pVideo->invertRGB = original->invertRGB;
|
|
|
|
// AK: If I'm not mistaken, tables are immutable (or at least being used as
|
|
// such)
|
|
|
|
pVideo->pRgbTable16 = original->pRgbTable16;
|
|
pVideo->pRgbTable32 = original->pRgbTable32;
|
|
|
|
return pVideo;
|
|
}
|
|
|
|
void videoDestroy(Video* pVideo)
|
|
{
|
|
free(pVideo);
|
|
}
|
|
|
|
void videoSetDeInterlace(Video* pVideo, int deInterlace)
|
|
{
|
|
pVideo->deInterlace = deInterlace;
|
|
}
|
|
|
|
void videoSetBlendFrames(Video* pVideo, int blendFrames)
|
|
{
|
|
frameBufferSetBlendFrames(blendFrames);
|
|
}
|
|
|
|
void videoSetColors(Video* pVideo, int saturation, int brightness, int contrast, int gamma)
|
|
{
|
|
pVideo->gamma = 1 + (MAX(0, MIN(200, gamma)) - 100) / 500.;
|
|
pVideo->saturation = MAX(0, MIN(200, saturation)) / 100.;
|
|
pVideo->brightness = MAX(0, MIN(200, brightness)) - 100.;
|
|
pVideo->contrast = MAX(0, MIN(200, contrast)) / 100.;
|
|
|
|
initRGBTable(pVideo);
|
|
}
|
|
|
|
void videoSetColorMode(Video* pVideo, VideoColorMode colorMode)
|
|
{
|
|
switch (colorMode) {
|
|
case VIDEO_GREEN:
|
|
pVideo->pRgbTable16 = pRgbTableGreen16;
|
|
pVideo->pRgbTable32 = pRgbTableGreen32;
|
|
break;
|
|
case VIDEO_BLACKWHITE:
|
|
pVideo->pRgbTable16 = pRgbTableWhite16;
|
|
pVideo->pRgbTable32 = pRgbTableWhite32;
|
|
break;
|
|
case VIDEO_AMBER:
|
|
pVideo->pRgbTable16 = pRgbTableAmber16;
|
|
pVideo->pRgbTable32 = pRgbTableAmber32;
|
|
break;
|
|
case VIDEO_COLOR:
|
|
default:
|
|
pVideo->pRgbTable16 = pRgbTableColor16;
|
|
pVideo->pRgbTable32 = pRgbTableColor32;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void videoSetPalMode(Video* pVideo, VideoPalMode palMode)
|
|
{
|
|
pVideo->palMode = palMode;
|
|
}
|
|
|
|
void videoSetRgbMode(Video* pVideo, int inverted)
|
|
{
|
|
int recalculate = pVideo->invertRGB != inverted;
|
|
|
|
pVideo->invertRGB = inverted;
|
|
|
|
if (recalculate) {
|
|
initRGBTable(pVideo);
|
|
}
|
|
}
|
|
|
|
|
|
void videoSetScanLines(Video* pVideo, int enable, int scanLinesPct)
|
|
{
|
|
pVideo->scanLinesEnable = enable;
|
|
pVideo->scanLinesPct = scanLinesPct;
|
|
}
|
|
|
|
void videoSetColorSaturation(Video* pVideo, int enable, int width)
|
|
{
|
|
pVideo->colorSaturationEnable = enable;
|
|
pVideo->colorSaturationWidth = width;
|
|
}
|
|
|
|
void videoUpdateAll(Video* video, Properties* properties)
|
|
{
|
|
videoSetColors(video, properties->video.saturation, properties->video.brightness, properties->video.contrast, properties->video.gamma);
|
|
videoSetScanLines(video, properties->video.scanlinesEnable, properties->video.scanlinesPct);
|
|
videoSetColorSaturation(video, properties->video.colorSaturationEnable, properties->video.colorSaturationWidth);
|
|
videoSetDeInterlace(video, properties->video.deInterlace);
|
|
|
|
switch (properties->video.monitorColor) {
|
|
case P_VIDEO_COLOR:
|
|
videoSetColorMode(video, VIDEO_COLOR);
|
|
break;
|
|
case P_VIDEO_BW:
|
|
videoSetColorMode(video, VIDEO_BLACKWHITE);
|
|
break;
|
|
case P_VIDEO_GREEN:
|
|
videoSetColorMode(video, VIDEO_GREEN);
|
|
break;
|
|
case P_VIDEO_AMBER:
|
|
videoSetColorMode(video, VIDEO_AMBER);
|
|
break;
|
|
}
|
|
|
|
switch (properties->video.monitorType) {
|
|
case P_VIDEO_PALNONE:
|
|
videoSetPalMode(video, VIDEO_PAL_FAST);
|
|
break;
|
|
case P_VIDEO_PALMON:
|
|
videoSetPalMode(video, VIDEO_PAL_MONITOR);
|
|
break;
|
|
case P_VIDEO_PALYC:
|
|
videoSetPalMode(video, VIDEO_PAL_SHARP);
|
|
break;
|
|
case P_VIDEO_PALNYC:
|
|
videoSetPalMode(video, VIDEO_PAL_SHARP_NOISE);
|
|
break;
|
|
case P_VIDEO_PALCOMP:
|
|
videoSetPalMode(video, VIDEO_PAL_BLUR);
|
|
break;
|
|
case P_VIDEO_PALNCOMP:
|
|
videoSetPalMode(video, VIDEO_PAL_BLUR_NOISE);
|
|
break;
|
|
case P_VIDEO_PALSCALE2X:
|
|
videoSetPalMode(video, VIDEO_PAL_SCALE2X);
|
|
break;
|
|
case P_VIDEO_PALHQ2X:
|
|
videoSetPalMode(video, VIDEO_PAL_HQ2X);
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
void colorSaturation_16(void* pBuffer, int width, int height, int pitch, int blur)
|
|
{
|
|
// This can be made more efficient by using 32 bit arithmetic and calculate
|
|
// two pixels at the time....
|
|
UInt16* pBuf = (UInt16*)pBuffer;
|
|
int w, h;
|
|
|
|
pitch /= (int)sizeof(UInt16);
|
|
|
|
switch (blur) {
|
|
case 0:
|
|
break;
|
|
|
|
case 1:
|
|
for (h = 0; h < height; h++) {
|
|
UInt16 p0 = pBuf[0] & 0xf7de;
|
|
for (w = 1; w < width; w++) {
|
|
UInt16 p1 = pBuf[w] & 0xf7de;
|
|
pBuf[w] = (UInt16)((p0 & 0x07e0) | (((p0 + p1) / 2) & 0x001f) | (p1 & 0xf800));
|
|
p0 = p1;
|
|
}
|
|
pBuf += pitch;
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
for (h = 0; h < height; h++) {
|
|
UInt16 p0 = pBuf[0];
|
|
UInt16 p1 = pBuf[1];
|
|
for (w = 2; w < width; w++) {
|
|
UInt16 p2 = pBuf[w];
|
|
pBuf[w] = (UInt16)((p0 & 0x07e0) | (p1 & 0x001f) | (((p1 + p2) / 2) & 0xf800));
|
|
p0 = p1;
|
|
p1 = p2;
|
|
}
|
|
pBuf += pitch;
|
|
}
|
|
break;
|
|
|
|
case 3:
|
|
for (h = 0; h < height; h++) {
|
|
UInt16 p0 = pBuf[0];
|
|
UInt16 p1 = pBuf[1];
|
|
for (w = 2; w < width; w++) {
|
|
UInt16 p2 = pBuf[w];
|
|
pBuf[w] = (UInt16)((p0 & 0x07e0) | (p1 & 0x001f) | (p2 & 0xf800));
|
|
p0 = p1;
|
|
p1 = p2;
|
|
}
|
|
pBuf += pitch;
|
|
}
|
|
break;
|
|
|
|
case 4:
|
|
for (h = 0; h < height; h++) {
|
|
UInt16 p0 = pBuf[0] & 0xf7de;
|
|
UInt16 p1 = pBuf[1] & 0xf7de;
|
|
UInt16 p2 = pBuf[2] & 0xf7de;
|
|
for (w = 3; w < width; w++) {
|
|
UInt16 p3 = pBuf[w] & 0xf7de;;
|
|
pBuf[w] = (UInt16)((((p0 + p1) / 2) & 0x07e0) | (p2 & 0x001f) | (p3 & 0xf800));
|
|
p0 = p1;
|
|
p1 = p2;
|
|
p2 = p3;
|
|
}
|
|
pBuf += pitch;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void colorSaturation_32(void* pBuffer, int width, int height, int pitch, int blur)
|
|
{
|
|
UInt32* pBuf = (UInt32*)pBuffer;
|
|
int w, h;
|
|
|
|
pitch /= (int)sizeof(UInt32);
|
|
|
|
switch (blur) {
|
|
case 0:
|
|
break;
|
|
|
|
case 1:
|
|
for (h = 0; h < height; h++) {
|
|
UInt32 p0 = pBuf[0] & 0xfefefe;
|
|
for (w = 1; w < width; w++) {
|
|
UInt32 p1 = pBuf[w] & 0xfefefe;
|
|
pBuf[w] = (p0 & 0x00ff00) | (((p0 + p1) / 2) & 0x0000ff) | (p1 & 0xff0000);
|
|
p0 = p1;
|
|
}
|
|
pBuf += pitch;
|
|
}
|
|
break;
|
|
|
|
case 2:
|
|
for (h = 0; h < height; h++) {
|
|
UInt32 p0 = pBuf[0];
|
|
UInt32 p1 = pBuf[1];
|
|
for (w = 2; w < width; w++) {
|
|
UInt32 p2 = pBuf[w];
|
|
pBuf[w] = (p0 & 0x00ff00) | (p1 & 0x0000ff) | (((p1 + p2) / 2) & 0xff0000);
|
|
p0 = p1;
|
|
p1 = p2;
|
|
}
|
|
pBuf += pitch;
|
|
}
|
|
break;
|
|
|
|
case 3:
|
|
for (h = 0; h < height; h++) {
|
|
UInt32 p0 = pBuf[0];
|
|
UInt32 p1 = pBuf[1];
|
|
for (w = 2; w < width; w++) {
|
|
UInt32 p2 = pBuf[w];
|
|
pBuf[w] = (p0 & 0x00ff00) | (p1 & 0x0000ff) | (p2 & 0xff0000);
|
|
p0 = p1;
|
|
p1 = p2;
|
|
}
|
|
pBuf += pitch;
|
|
}
|
|
break;
|
|
|
|
case 4:
|
|
for (h = 0; h < height; h++) {
|
|
UInt32 p0 = pBuf[0] & 0xfefefe;
|
|
UInt32 p1 = pBuf[1] & 0xfefefe;
|
|
UInt32 p2 = pBuf[2] & 0xfefefe;
|
|
for (w = 3; w < width; w++) {
|
|
UInt32 p3 = pBuf[w] & 0xfefefe;;
|
|
pBuf[w] = (((p0 + p1) / 2) & 0x00ff00) | (p2 & 0x0000ff) | (p3 & 0xff0000);
|
|
p0 = p1;
|
|
p1 = p2;
|
|
p2 = p3;
|
|
}
|
|
pBuf += pitch;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void scanLines_16(void* pBuffer, int width, int height, int pitch, int scanLinesPct)
|
|
{
|
|
UInt32* pBuf = (UInt32*)pBuffer;
|
|
int w, h;
|
|
|
|
if (scanLinesPct == 100) {
|
|
return;
|
|
}
|
|
|
|
pitch = pitch * 2 / (int)sizeof(UInt32);
|
|
scanLinesPct = scanLinesPct * 32 / 100;
|
|
height /= 2;
|
|
width /= 2;
|
|
|
|
if (scanLinesPct == 0) {
|
|
for (h = 0; h < height; h++) {
|
|
memset(pBuf, 0, width * sizeof(UInt32));
|
|
pBuf += pitch;
|
|
}
|
|
return;
|
|
}
|
|
|
|
for (h = 0; h < height; h++) {
|
|
for (w = 0; w < width; w++) {
|
|
UInt32 pixel = pBuf[w];
|
|
UInt32 a = (((pixel & 0x07e0f81f) * scanLinesPct) & 0xfc1f03e0) >> 5;
|
|
UInt32 b = (((pixel >> 5) & 0x07c0f83f) * scanLinesPct) & 0xf81f07e0;
|
|
pBuf[w] = a | b;
|
|
}
|
|
pBuf += pitch;
|
|
}
|
|
}
|
|
|
|
void scanLines_32_core(UInt32* pBuf, int width, int scanLinesPct, int hint) {
|
|
int w;
|
|
for (w = 0; w < width; w++) {
|
|
UInt32 pixel = pBuf[w];
|
|
UInt32 a = (((pixel & 0xff00ff) * scanLinesPct) & 0xff00ff00) >> 8;
|
|
UInt32 b = (((pixel >> 8)& 0xff00ff) * scanLinesPct) & 0xff00ff00;
|
|
pBuf[w] = a | b;
|
|
}
|
|
}
|
|
|
|
#ifndef NO_ASM
|
|
void scanLines_32_core_SSE(UInt32* pBuf, int width, int scanLinesPct, int hint) {
|
|
|
|
#ifdef __GNUC__
|
|
__asm__ (
|
|
"movl %1,%%ecx \n\t" // width
|
|
"shrl $2,%%ecx \n\t"
|
|
"movl %0,%%eax \n\t" // pbuf
|
|
"movl %3,%%ebx \n\t" // hint
|
|
"pxor %%mm0,%%mm0 \n\t"
|
|
"movd %2,%%mm1 \n\t" // scanLinesPct
|
|
"punpcklwd %%mm1,%%mm1 \n\t"
|
|
"punpckldq %%mm1,%%mm1 \n\t"
|
|
"psllw $8,%%mm1 \n\t"
|
|
"inner_loop5: \n\t"
|
|
"movq (%%eax),%%mm2 \n\t"
|
|
"movq 8(%%eax),%%mm4 \n\t"
|
|
"movq %%mm2,%%mm3 \n\t"
|
|
"punpcklbw %%mm0,%%mm2 \n\t"
|
|
"movq %%mm4,%%mm5 \n\t"
|
|
"pmulhuw %%mm1,%%mm2 \n\t"
|
|
"punpcklbw %%mm0,%%mm4 \n\t"
|
|
"punpckhbw %%mm0,%%mm3 \n\t"
|
|
"prefetcht1 (%%eax,%%ebx) \n\t"
|
|
"pmulhuw %%mm1,%%mm4 \n\t"
|
|
"punpckhbw %%mm0,%%mm5 \n\t"
|
|
"addl $16,%%eax \n\t"
|
|
"pmulhuw %%mm1,%%mm3 \n\t"
|
|
"pmulhuw %%mm1,%%mm5 \n\t"
|
|
"packuswb %%mm3,%%mm2 \n\t"
|
|
"packuswb %%mm5,%%mm4 \n\t"
|
|
"movq %%mm2,-16(%%eax) \n\t"
|
|
"decl %%ecx \n\t"
|
|
"movq %%mm4,-8(%%eax) \n\t"
|
|
|
|
"jnz inner_loop5 \n\t"
|
|
"emms \n\t"
|
|
:
|
|
: "m" (pBuf), "m" (width), "m" (scanLinesPct), "m" (hint)
|
|
: "%eax", "%ebx", "%ecx"
|
|
);
|
|
#else
|
|
__asm {
|
|
mov ecx,width
|
|
shr ecx,2
|
|
mov eax,pBuf
|
|
mov ebx,hint
|
|
pxor mm0,mm0
|
|
movd mm1,scanLinesPct
|
|
punpcklwd mm1,mm1
|
|
punpckldq mm1,mm1
|
|
psllw mm1,8
|
|
inner_loop:
|
|
movq mm2,[eax]
|
|
movq mm4,[eax+8]
|
|
movq mm3,mm2
|
|
punpcklbw mm2,mm0
|
|
movq mm5,mm4
|
|
pmulhuw mm2,mm1
|
|
punpcklbw mm4,mm0
|
|
punpckhbw mm3,mm0
|
|
prefetcht1 [eax+ebx]
|
|
pmulhuw mm4,mm1
|
|
punpckhbw mm5,mm0
|
|
add eax,16
|
|
pmulhuw mm3,mm1
|
|
pmulhuw mm5,mm1
|
|
packuswb mm2,mm3
|
|
packuswb mm4,mm5
|
|
movq [eax-16],mm2
|
|
dec ecx
|
|
movq [eax-8],mm4
|
|
|
|
jnz inner_loop
|
|
emms
|
|
}
|
|
#endif
|
|
|
|
}
|
|
#endif
|
|
|
|
/* 5500 units -> 2500 units */
|
|
void scanLines_32(void* pBuffer, int width, int height, int pitch, int scanLinesPct)
|
|
{
|
|
UInt32* pBuf = (UInt32*)pBuffer;
|
|
int h;
|
|
void (*core) (UInt32* , int , int , int ) ;
|
|
|
|
#ifndef NO_ASM
|
|
int hasSSE=0;
|
|
const int SSEbit=1<<25;
|
|
|
|
#ifdef __GNUC__
|
|
__asm__ (
|
|
"movl $1,%%eax \n\t"
|
|
"cpuid \n\t"
|
|
"andl $0x2000000,%%edx \n\t"
|
|
"movl %%edx,%0 \n\t"
|
|
: "=r" (hasSSE) : : "%eax", "%ebx", "%ecx", "%edx"
|
|
);
|
|
#else
|
|
__asm {
|
|
mov eax,1
|
|
cpuid
|
|
and edx,SSEbit
|
|
mov hasSSE,edx
|
|
}
|
|
#endif
|
|
|
|
hasSSE = 1;
|
|
core=hasSSE? scanLines_32_core_SSE: scanLines_32_core;
|
|
/*rdtsc_start_timer(0);*/
|
|
#else
|
|
core=scanLines_32_core;
|
|
#endif
|
|
|
|
if (scanLinesPct == 100) {
|
|
/*rdtsc_end_timer(0);*/
|
|
return;
|
|
}
|
|
|
|
pitch = pitch * 2 / (int)sizeof(UInt32);
|
|
scanLinesPct = scanLinesPct * 255 / 100;
|
|
height /= 2;
|
|
|
|
if (scanLinesPct == 0) {
|
|
for (h = 0; h < height; h++) {
|
|
memset(pBuf, 0, width * sizeof(UInt32));
|
|
pBuf += pitch;
|
|
}
|
|
/*rdtsc_end_timer(0);*/
|
|
return;
|
|
}
|
|
|
|
for (h = 0; h < height; h++) {
|
|
core (pBuf,width,scanLinesPct,pitch*4);
|
|
pBuf += pitch;
|
|
}
|
|
/*rdtsc_end_timer(0);*/
|
|
}
|
|
|
|
static int videoRender240(Video* pVideo, FrameBuffer* frame, int bitDepth, int zoom,
|
|
void* pDst, int dstOffset, int dstPitch, int canChangeZoom)
|
|
{
|
|
pDst = (char*)pDst + zoom * dstOffset;
|
|
|
|
switch (bitDepth) {
|
|
case 16:
|
|
switch (pVideo->palMode) {
|
|
case VIDEO_PAL_FAST:
|
|
if (zoom == 2) {
|
|
if (pVideo->scanLinesEnable || pVideo->colorSaturationEnable || canChangeZoom == 0) {
|
|
copy_2x2_16(frame, pDst, dstPitch, pVideo->pRgbTable16);
|
|
}
|
|
else {
|
|
int h = frame->lines;
|
|
while (--h >= 0 && !frame->line[h].doubleWidth);
|
|
if (h) copy_2x2_16(frame, pDst, dstPitch, pVideo->pRgbTable16);
|
|
else {
|
|
copy_1x1_16(frame, pDst, dstPitch, pVideo->pRgbTable16);
|
|
zoom = 1;
|
|
}
|
|
}
|
|
}
|
|
else copy_1x1_16(frame, pDst, dstPitch, pVideo->pRgbTable16);
|
|
break;
|
|
case VIDEO_PAL_MONITOR:
|
|
if (zoom == 2) copyMonitorPAL_2x2_16(frame, pDst, dstPitch, pVideo->pRgbTable16, 0);
|
|
else copyPAL_1x1_16(frame, pDst, dstPitch, pVideo->pRgbTable16, 0);
|
|
break;
|
|
case VIDEO_PAL_SHARP:
|
|
if (zoom == 2) copySharpPAL_2x2_16(frame, pDst, dstPitch, pVideo->pRgbTable16, 0);
|
|
else copyPAL_1x1_16(frame, pDst, dstPitch, pVideo->pRgbTable16, 0);
|
|
break;
|
|
case VIDEO_PAL_SHARP_NOISE:
|
|
if (zoom == 2) copySharpPAL_2x2_16(frame, pDst, dstPitch, pVideo->pRgbTable16, 1);
|
|
else copyPAL_1x1_16(frame, pDst, dstPitch, pVideo->pRgbTable16, 1);
|
|
break;
|
|
case VIDEO_PAL_BLUR:
|
|
if (zoom == 2) copyMonitorPAL_2x2_16(frame, pDst, dstPitch, pVideo->pRgbTable16, 0);
|
|
else copyPAL_1x1_16(frame, pDst, dstPitch, pVideo->pRgbTable16, 0);
|
|
break;
|
|
case VIDEO_PAL_BLUR_NOISE:
|
|
if (zoom == 2) copyMonitorPAL_2x2_16(frame, pDst, dstPitch, pVideo->pRgbTable16, 1);
|
|
else copyPAL_1x1_16(frame, pDst, dstPitch, pVideo->pRgbTable16, 1);
|
|
break;
|
|
case VIDEO_PAL_HQ2X: // Can't do 16bit hq2x so just use scale2x instead
|
|
case VIDEO_PAL_SCALE2X:
|
|
if (zoom==2) {
|
|
if (frame->line[0].doubleWidth == 0 && frame->interlace == INTERLACE_NONE) {
|
|
scale2x_2x2_16(frame, pDst, dstPitch, pVideo->pRgbTable16);
|
|
}
|
|
else {
|
|
copy_2x2_16(frame, pDst, dstPitch, pVideo->pRgbTable16);
|
|
}
|
|
}
|
|
else {
|
|
copy_1x1_16(frame, pDst, dstPitch, pVideo->pRgbTable16);
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
case 32:
|
|
switch (pVideo->palMode) {
|
|
case VIDEO_PAL_FAST:
|
|
if (zoom == 2) {
|
|
if (pVideo->scanLinesEnable || pVideo->colorSaturationEnable || canChangeZoom == 0) {
|
|
copy_2x2_32(frame, pDst, dstPitch, pVideo->pRgbTable32);
|
|
}
|
|
else {
|
|
int h = frame->lines;
|
|
while (--h >= 0 && !frame->line[h].doubleWidth);
|
|
if (h) copy_2x2_32(frame, pDst, dstPitch, pVideo->pRgbTable32);
|
|
else {
|
|
copy_1x1_32(frame, pDst, dstPitch, pVideo->pRgbTable32);
|
|
zoom = 1;
|
|
}
|
|
}
|
|
}
|
|
else copy_1x1_32(frame, pDst, dstPitch, pVideo->pRgbTable32);
|
|
break;
|
|
case VIDEO_PAL_MONITOR:
|
|
if (zoom == 2) copyMonitorPAL_2x2_32(frame, pDst, dstPitch, pVideo->pRgbTable32, 0);
|
|
else copyPAL_1x1_32(frame, pDst, dstPitch, pVideo->pRgbTable32, 0);
|
|
break;
|
|
case VIDEO_PAL_SHARP:
|
|
if (zoom == 2) copySharpPAL_2x2_32(frame, pDst, dstPitch, pVideo->pRgbTable32, 0);
|
|
else copy_1x1_32(frame, pDst, dstPitch, pVideo->pRgbTable32);
|
|
break;
|
|
case VIDEO_PAL_SHARP_NOISE:
|
|
if (zoom == 2) copySharpPAL_2x2_32(frame, pDst, dstPitch, pVideo->pRgbTable32, 1);
|
|
else copyPAL_1x1_32(frame, pDst, dstPitch, pVideo->pRgbTable32, 1);
|
|
break;
|
|
case VIDEO_PAL_BLUR:
|
|
if (zoom == 2) copyPAL_2x2_32(frame, pDst, dstPitch, pVideo->pRgbTable32, 0);
|
|
else copyPAL_1x1_32(frame, pDst, dstPitch, pVideo->pRgbTable32, 0);
|
|
break;
|
|
case VIDEO_PAL_BLUR_NOISE:
|
|
if (zoom == 2) copyPAL_2x2_32(frame, pDst, dstPitch, pVideo->pRgbTable32, 1);
|
|
else copyPAL_1x1_32(frame, pDst, dstPitch, pVideo->pRgbTable32, 1);
|
|
break;
|
|
case VIDEO_PAL_SCALE2X:
|
|
if (zoom==2) {
|
|
if (frame->line[0].doubleWidth == 0 && frame->interlace == INTERLACE_NONE) {
|
|
scale2x_2x2_32(frame, pDst, dstPitch, pVideo->pRgbTable32);
|
|
}
|
|
else {
|
|
copy_2x2_32(frame, pDst, dstPitch, pVideo->pRgbTable32);
|
|
}
|
|
}
|
|
else {
|
|
copy_1x1_32(frame, pDst, dstPitch, pVideo->pRgbTable32);
|
|
}
|
|
break;
|
|
case VIDEO_PAL_HQ2X:
|
|
if (zoom==2) {
|
|
if (frame->line[0].doubleWidth == 0 && frame->interlace == INTERLACE_NONE) {
|
|
if (canChangeZoom > 0) {
|
|
pDst = (char*)pDst + dstOffset;
|
|
hq3x_2x2_32(frame, pDst, dstPitch, pVideo->pRgbTable16);
|
|
zoom =3;
|
|
}
|
|
else {
|
|
hq2x_2x2_32(frame, pDst, dstPitch, pVideo->pRgbTable16);
|
|
}
|
|
}
|
|
else {
|
|
copy_2x2_32(frame, pDst, dstPitch, pVideo->pRgbTable32);
|
|
}
|
|
}
|
|
else {
|
|
copy_1x1_32(frame, pDst, dstPitch, pVideo->pRgbTable32);
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
return zoom;
|
|
}
|
|
|
|
static int videoRender480(Video* pVideo, FrameBuffer* frame, int bitDepth, int zoom,
|
|
void* pDst, int dstOffset, int dstPitch, int canChangeZoom)
|
|
{
|
|
pDst = (char*)pDst + zoom * dstOffset;
|
|
|
|
switch (bitDepth) {
|
|
case 16:
|
|
switch (pVideo->palMode) {
|
|
default:
|
|
case VIDEO_PAL_FAST:
|
|
case VIDEO_PAL_SCALE2X:
|
|
case VIDEO_PAL_HQ2X:
|
|
if (zoom == 2) copy_2x1_16(frame, pDst, dstPitch, pVideo->pRgbTable16);
|
|
else copy_1x05_16(frame, pDst, dstPitch, pVideo->pRgbTable16);
|
|
break;
|
|
case VIDEO_PAL_MONITOR:
|
|
if (zoom == 2) copyMonitorPAL_2x1_16(frame, pDst, dstPitch, pVideo->pRgbTable16, 1);
|
|
else copy_1x05_16(frame, pDst, dstPitch, pVideo->pRgbTable16);
|
|
break;
|
|
case VIDEO_PAL_SHARP:
|
|
if (zoom == 2) copySharpPAL_2x1_16(frame, pDst, dstPitch, pVideo->pRgbTable16, 0);
|
|
else copy_1x05_16(frame, pDst, dstPitch, pVideo->pRgbTable16);
|
|
break;
|
|
case VIDEO_PAL_SHARP_NOISE:
|
|
if (zoom == 2) copySharpPAL_2x1_16(frame, pDst, dstPitch, pVideo->pRgbTable16, 1);
|
|
else copy_1x05_16(frame, pDst, dstPitch, pVideo->pRgbTable16);
|
|
break;
|
|
case VIDEO_PAL_BLUR:
|
|
if (zoom == 2) copyMonitorPAL_2x1_16(frame, pDst, dstPitch, pVideo->pRgbTable16, 0);
|
|
else copy_1x05_16(frame, pDst, dstPitch, pVideo->pRgbTable16);
|
|
break;
|
|
case VIDEO_PAL_BLUR_NOISE:
|
|
if (zoom == 2) copyMonitorPAL_2x1_16(frame, pDst, dstPitch, pVideo->pRgbTable16, 1);
|
|
else copy_1x05_16(frame, pDst, dstPitch, pVideo->pRgbTable16);
|
|
break;
|
|
}
|
|
break;
|
|
case 32:
|
|
switch (pVideo->palMode) {
|
|
default:
|
|
case VIDEO_PAL_FAST:
|
|
case VIDEO_PAL_SCALE2X:
|
|
case VIDEO_PAL_HQ2X:
|
|
if (zoom == 2) copy_2x1_32(frame, pDst, dstPitch, pVideo->pRgbTable32);
|
|
else copy_1x05_32(frame, pDst, dstPitch, pVideo->pRgbTable32);
|
|
break;
|
|
case VIDEO_PAL_MONITOR:
|
|
if (zoom == 2) copyMonitorPAL_2x1_32(frame, pDst, dstPitch, pVideo->pRgbTable32, 1);
|
|
else copyPAL_1x05_32(frame, pDst, dstPitch, pVideo->pRgbTable32, 0);
|
|
break;
|
|
case VIDEO_PAL_SHARP:
|
|
if (zoom == 2) copySharpPAL_2x1_32(frame, pDst, dstPitch, pVideo->pRgbTable32, 0);
|
|
else copy_1x05_32(frame, pDst, dstPitch, pVideo->pRgbTable32);
|
|
break;
|
|
case VIDEO_PAL_SHARP_NOISE:
|
|
if (zoom == 2) copySharpPAL_2x1_32(frame, pDst, dstPitch, pVideo->pRgbTable32, 1);
|
|
else copyPAL_1x05_32(frame, pDst, dstPitch, pVideo->pRgbTable32, 1);
|
|
break;
|
|
case VIDEO_PAL_BLUR:
|
|
if (zoom == 2) copyPAL_2x1_32(frame, pDst, dstPitch, pVideo->pRgbTable32, 0);
|
|
else copyPAL_1x05_32(frame, pDst, dstPitch, pVideo->pRgbTable32, 0);
|
|
break;
|
|
case VIDEO_PAL_BLUR_NOISE:
|
|
if (zoom == 2) copyPAL_2x1_32(frame, pDst, dstPitch, pVideo->pRgbTable32, 1);
|
|
else copyPAL_1x05_32(frame, pDst, dstPitch, pVideo->pRgbTable32, 1);
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
return zoom;
|
|
}
|
|
|
|
int videoRender(Video* pVideo, FrameBuffer* frame, int bitDepth, int zoom,
|
|
void* pDst, int dstOffset, int dstPitch, int canChangeZoom)
|
|
{
|
|
if (frame == NULL) {
|
|
return zoom;
|
|
}
|
|
|
|
if (frame->interlace != INTERLACE_NONE && pVideo->deInterlace) {
|
|
frame = frameBufferDeinterlace(frame);
|
|
}
|
|
|
|
if (frame->lines <= 240) {
|
|
zoom = videoRender240(pVideo, frame, bitDepth, zoom, pDst, dstOffset, dstPitch, canChangeZoom);
|
|
}
|
|
else {
|
|
zoom = videoRender480(pVideo, frame, bitDepth, zoom, pDst, dstOffset, dstPitch, canChangeZoom);
|
|
}
|
|
|
|
switch (bitDepth) {
|
|
case 16:
|
|
if (pVideo->colorSaturationEnable) {
|
|
colorSaturation_16(pDst, 320 * zoom, 240 * zoom, dstPitch, pVideo->colorSaturationWidth);
|
|
}
|
|
|
|
if (pVideo->scanLinesEnable) {
|
|
scanLines_16(pDst, 320 * zoom, 240 * zoom, dstPitch, pVideo->scanLinesPct);
|
|
}
|
|
|
|
break;
|
|
case 32:
|
|
if (pVideo->colorSaturationEnable) {
|
|
colorSaturation_32(pDst, 320 * zoom, 240 * zoom, dstPitch, pVideo->colorSaturationWidth);
|
|
}
|
|
|
|
if (pVideo->scanLinesEnable) {
|
|
scanLines_32(pDst, 320 * zoom, 240 * zoom, dstPitch, pVideo->scanLinesPct);
|
|
}
|
|
break;
|
|
}
|
|
|
|
return zoom;
|
|
}
|
|
#endif
|