Included the phase coefficient computation from the X driver implementation.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17401 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
d2a76f7406
commit
72119ffac8
@ -4,12 +4,16 @@
|
||||
*
|
||||
* Authors:
|
||||
* Axel Dörfler, axeld@pinc-software.de
|
||||
*
|
||||
* The phase coefficient computation was taken from the X driver written by
|
||||
* Alan Hourihane and David Dawes.
|
||||
*/
|
||||
|
||||
|
||||
#include "accelerant.h"
|
||||
#include "accelerant_protos.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
@ -22,6 +26,156 @@ extern "C" void _sPrintf(const char *format, ...);
|
||||
#endif
|
||||
|
||||
|
||||
#define NUM_HORIZONTAL_TAPS 5
|
||||
#define NUM_VERTICAL_TAPS 3
|
||||
#define NUM_HORIZONTAL_UV_TAPS 3
|
||||
#define NUM_VERTICAL_UV_TAPS 3
|
||||
#define NUM_PHASES 17
|
||||
#define MAX_TAPS 5
|
||||
|
||||
struct phase_coefficient {
|
||||
uint8 sign;
|
||||
uint8 exponent;
|
||||
uint16 mantissa;
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
Splits the coefficient floating point value into the 3 components
|
||||
sign, mantissa, and exponent.
|
||||
*/
|
||||
static bool
|
||||
split_coefficient(double &coefficient, int32 mantissaSize,
|
||||
phase_coefficient &splitCoefficient)
|
||||
{
|
||||
double absCoefficient = fabs(coefficient);
|
||||
|
||||
int sign;
|
||||
if (coefficient < 0.0)
|
||||
sign = 1;
|
||||
else
|
||||
sign = 0;
|
||||
|
||||
int32 intCoefficient, res;
|
||||
int32 maxValue = 1 << mantissaSize;
|
||||
res = 12 - mantissaSize;
|
||||
|
||||
if ((intCoefficient = (int)(absCoefficient * 4 * maxValue + 0.5)) < maxValue) {
|
||||
splitCoefficient.exponent = 3;
|
||||
splitCoefficient.mantissa = intCoefficient << res;
|
||||
coefficient = (double)intCoefficient / (double)(4 * maxValue);
|
||||
} else if ((intCoefficient = (int)(absCoefficient * 2 * maxValue + 0.5)) < maxValue) {
|
||||
splitCoefficient.exponent = 2;
|
||||
splitCoefficient.mantissa = intCoefficient << res;
|
||||
coefficient = (double)intCoefficient / (double)(2 * maxValue);
|
||||
} else if ((intCoefficient = (int)(absCoefficient * maxValue + 0.5)) < maxValue) {
|
||||
splitCoefficient.exponent = 1;
|
||||
splitCoefficient.mantissa = intCoefficient << res;
|
||||
coefficient = (double)intCoefficient / (double)maxValue;
|
||||
} else if ((intCoefficient = (int)(absCoefficient * maxValue * 0.5 + 0.5)) < maxValue) {
|
||||
splitCoefficient.exponent = 0;
|
||||
splitCoefficient.mantissa = intCoefficient << res;
|
||||
coefficient = (double)intCoefficient / (double)(maxValue / 2);
|
||||
} else {
|
||||
// coefficient out of range
|
||||
return false;
|
||||
}
|
||||
|
||||
splitCoefficient.sign = sign;
|
||||
if (sign)
|
||||
coefficient = -coefficient;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
update_coefficients(int32 taps, double filterCutOff, bool horizontal, bool isY,
|
||||
phase_coefficient *splitCoefficients)
|
||||
{
|
||||
if (filterCutOff < 1)
|
||||
filterCutOff = 1;
|
||||
if (filterCutOff > 3)
|
||||
filterCutOff = 3;
|
||||
|
||||
bool isVerticalUV = !horizontal && !isY;
|
||||
int32 mantissaSize = horizontal ? 7 : 6;
|
||||
|
||||
double rawCoefficients[MAX_TAPS * 32], coefficients[NUM_PHASES][MAX_TAPS];
|
||||
|
||||
int32 num = taps * 16;
|
||||
for (int32 i = 0; i < num * 2; i++) {
|
||||
double sinc;
|
||||
double value = (1.0 / filterCutOff) * taps * PI * (i - num) / (2 * num);
|
||||
if (value == 0.0)
|
||||
sinc = 1.0;
|
||||
else
|
||||
sinc = sin(value) / value;
|
||||
|
||||
// Hamming window
|
||||
double window = (0.5 - 0.5 * cos(i * PI / num));
|
||||
rawCoefficients[i] = sinc * window;
|
||||
}
|
||||
|
||||
for (int32 i = 0; i < NUM_PHASES; i++) {
|
||||
// Normalise the coefficients
|
||||
double sum = 0.0;
|
||||
int32 pos;
|
||||
for (int32 j = 0; j < taps; j++) {
|
||||
pos = i + j * 32;
|
||||
sum += rawCoefficients[pos];
|
||||
}
|
||||
for (int32 j = 0; j < taps; j++) {
|
||||
pos = i + j * 32;
|
||||
coefficients[i][j] = rawCoefficients[pos] / sum;
|
||||
}
|
||||
|
||||
// split them into sign/mantissa/exponent
|
||||
for (int32 j = 0; j < taps; j++) {
|
||||
pos = j + i * taps;
|
||||
|
||||
split_coefficient(coefficients[i][j], mantissaSize
|
||||
+ (((j == (taps - 1) / 2) && !isVerticalUV) ? 2 : 0),
|
||||
splitCoefficients[pos]);
|
||||
}
|
||||
|
||||
int32 tapAdjust[MAX_TAPS];
|
||||
tapAdjust[0] = (taps - 1) / 2;
|
||||
for (int32 j = 1, k = 1; j <= tapAdjust[0]; j++, k++) {
|
||||
tapAdjust[k] = tapAdjust[0] - j;
|
||||
tapAdjust[++k] = tapAdjust[0] + j;
|
||||
}
|
||||
|
||||
// Adjust the coefficients
|
||||
sum = 0.0;
|
||||
for (int32 j = 0; j < taps; j++) {
|
||||
sum += coefficients[i][j];
|
||||
}
|
||||
|
||||
if (sum != 1.0) {
|
||||
for (int32 k = 0; k < taps; k++) {
|
||||
int32 tap2Fix = tapAdjust[k];
|
||||
double diff = 1.0 - sum;
|
||||
|
||||
coefficients[i][tap2Fix] += diff;
|
||||
pos = tap2Fix + i * taps;
|
||||
|
||||
split_coefficient(coefficients[i][tap2Fix], mantissaSize
|
||||
+ (((tap2Fix == (taps - 1) / 2) && !isVerticalUV) ? 2 : 0),
|
||||
splitCoefficients[pos]);
|
||||
|
||||
sum = 0.0;
|
||||
for (int32 j = 0; j < taps; j++) {
|
||||
sum += coefficients[i][j];
|
||||
}
|
||||
if (sum == 1.0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
set_color_key(uint8 red, uint8 green, uint8 blue,
|
||||
uint8 redMask, uint8 greenMask, uint8 blueMask)
|
||||
@ -78,7 +232,7 @@ update_overlay(bool updateCoefficients)
|
||||
write_to_ring(ringBuffer, COMMAND_NOOP);
|
||||
write_to_ring(ringBuffer, COMMAND_OVERLAY_FLIP | COMMAND_OVERLAY_CONTINUE);
|
||||
write_to_ring(ringBuffer, (uint32)gInfo->shared_info->physical_overlay_registers
|
||||
/*| (updateCoefficients ? OVERLAY_UPDATE_COEFFICIENTS : 0)*/);
|
||||
| (updateCoefficients ? OVERLAY_UPDATE_COEFFICIENTS : 0));
|
||||
ring_command_complete(ringBuffer);
|
||||
|
||||
TRACE(("update overlay: UPDATE: %lx, TEST: %lx, STATUS: %lx, EXTENDED_STATUS: %lx\n",
|
||||
@ -103,7 +257,7 @@ show_overlay(void)
|
||||
write_to_ring(ringBuffer, COMMAND_NOOP);
|
||||
write_to_ring(ringBuffer, COMMAND_OVERLAY_FLIP | COMMAND_OVERLAY_ON);
|
||||
write_to_ring(ringBuffer, (uint32)gInfo->shared_info->physical_overlay_registers
|
||||
/*| OVERLAY_UPDATE_COEFFICIENTS*/);
|
||||
| OVERLAY_UPDATE_COEFFICIENTS);
|
||||
ring_command_complete(ringBuffer);
|
||||
}
|
||||
|
||||
@ -419,9 +573,37 @@ intel_configure_overlay(overlay_token overlayToken, const overlay_buffer *buffer
|
||||
|
||||
if (verticalScale != gInfo->last_vertical_overlay_scale
|
||||
|| horizontalScale != gInfo->last_horizontal_overlay_scale) {
|
||||
// TODO: recompute phase coefficients (take from X driver)
|
||||
// Recompute phase coefficients (taken from X driver)
|
||||
updateCoefficients = true;
|
||||
|
||||
phase_coefficient coefficients[NUM_HORIZONTAL_TAPS * NUM_PHASES];
|
||||
update_coefficients(NUM_HORIZONTAL_TAPS, horizontalScale / 4096.0,
|
||||
true, true, coefficients);
|
||||
|
||||
phase_coefficient coefficientsUV[NUM_HORIZONTAL_UV_TAPS * NUM_PHASES];
|
||||
update_coefficients(NUM_HORIZONTAL_UV_TAPS, horizontalScaleUV / 4096.0,
|
||||
true, false, coefficientsUV);
|
||||
|
||||
int32 pos = 0;
|
||||
for (int32 i = 0; i < NUM_PHASES; i++) {
|
||||
for (int32 j = 0; j < NUM_HORIZONTAL_TAPS; j++) {
|
||||
registers->horizontal_coefficients_rgb[pos] = coefficients[pos].sign << 15
|
||||
| coefficients[pos].exponent << 12
|
||||
| coefficients[pos].mantissa;
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
pos = 0;
|
||||
for (int32 i = 0; i < NUM_PHASES; i++) {
|
||||
for (int32 j = 0; j < NUM_HORIZONTAL_UV_TAPS; j++) {
|
||||
registers->horizontal_coefficients_uv[pos] = coefficientsUV[pos].sign << 15
|
||||
| coefficientsUV[pos].exponent << 12
|
||||
| coefficientsUV[pos].mantissa;
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
||||
gInfo->last_vertical_overlay_scale = verticalScale;
|
||||
gInfo->last_horizontal_overlay_scale = horizontalScale;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user