Haiku ATI video driver adapted from the X.org ATI driver which has the
following copyright:
Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
Precision Insight, Inc., Cedar Park, Texas, and
VA Linux Systems Inc., Fremont, California.
Copyright 2011 Haiku, Inc. All rights reserved.
Distributed under the terms of the MIT license.
Authors:
Gerald Zajac
*/
#include "accelerant.h"
#include "rage128.h"
static uint32 sCurrentKeyColor = 0;
static uint32 sCurrentKeyMask = 0;
bool
Rage128_DisplayOverlay(const overlay_window* window,
const overlay_buffer* buffer)
{
SharedInfo& si = *gInfo.sharedInfo;
if (window == NULL || buffer == NULL)
return false;
if (buffer->space != B_YCbCr422)
return false;
uint32 keyColor = 0;
uint32 keyMask = 0;
switch (si.displayMode.bitsPerPixel) {
case 15:
keyMask = 0x7fff;
keyColor = (window->blue.value & window->blue.mask) << 0
| (window->green.value & window->green.mask) << 5
| (window->red.value & window->red.mask) << 10;
break;
case 16:
keyMask = 0xffff;
keyColor = (window->blue.value & window->blue.mask) << 0
| (window->green.value & window->green.mask) << 5
| (window->red.value & window->red.mask) << 11;
break;
default:
keyMask = 0xffffffff;
keyColor = (window->blue.value & window->blue.mask) << 0
| (window->green.value & window->green.mask) << 8
| (window->red.value & window->red.mask) << 16
| (window->alpha.value & window->alpha.mask) << 24;
break;
}
if (keyColor != sCurrentKeyColor || keyMask != sCurrentKeyMask)
{
TRACE("Rage128_DisplayOverlay() initializing overlay video\n");
OUTREG(R128_OV0_SCALE_CNTL, 0);
OUTREG(R128_OV0_EXCLUSIVE_HORZ, 0);
OUTREG(R128_OV0_AUTO_FLIP_CNTL, 0);
OUTREG(R128_OV0_FILTER_CNTL, 0x0000000f);
const uint32 brightness = 0;
const uint32 saturation = 16;
OUTREG(R128_OV0_COLOUR_CNTL, brightness | saturation << 8
| saturation << 16);
OUTREG(R128_OV0_GRAPHICS_KEY_MSK, keyMask);
OUTREG(R128_OV0_GRAPHICS_KEY_CLR, keyColor);
OUTREG(R128_OV0_KEY_CNTL, R128_GRAPHIC_KEY_FN_NE);
OUTREG(R128_OV0_TEST, 0);
sCurrentKeyColor = keyColor;
sCurrentKeyMask = keyMask;
}
uint32 ecpDiv;
if (si.displayMode.timing.pixel_clock < 125000)
ecpDiv = 0;
else if (si.displayMode.timing.pixel_clock < 250000)
ecpDiv = 1;
else
ecpDiv = 2;
SetPLLReg(R128_VCLK_ECP_CNTL, ecpDiv << 8, R128_ECP_DIV_MASK);
int32 vertInc = (buffer->height << 20) / window->height;
int32 horzInc = (buffer->width << (12 + ecpDiv)) / window->width;
int32 stepBy = 1;
while (horzInc >= (2 << 12)) {
stepBy++;
horzInc >>= 1;
}
int32 x1 = window->h_start;
int32 y1 = window->v_start;
int32 x2 = window->h_start + window->width;
int32 y2 = window->v_start + window->height;
int32 left = x1;
int32 tmp = (left & 0x0003ffff) + 0x00028000 + (horzInc << 3);
int32 p1_h_accum_init = ((tmp << 4) & 0x000f8000) |
((tmp << 12) & 0xf0000000);
tmp = ((left >> 1) & 0x0001ffff) + 0x00028000 + (horzInc << 2);
int32 p23_h_accum_init = ((tmp << 4) & 0x000f8000) |
((tmp << 12) & 0x70000000);
tmp = (y1 & 0x0000ffff) + 0x00018000;
int32 p1_v_accum_init = ((tmp << 4) & 0x03ff8000) | 0x00000001;
uint32 offset = (uint32)((addr_t)buffer->buffer - si.videoMemAddr);
OUTREG(R128_OV0_REG_LOAD_CNTL, 1);
while (!(INREG(R128_OV0_REG_LOAD_CNTL) & (1 << 3)))
;
OUTREG(R128_OV0_H_INC, horzInc | ((horzInc >> 1) << 16));
OUTREG(R128_OV0_STEP_BY, stepBy | (stepBy << 8));
OUTREG(R128_OV0_Y_X_START, x1 | y1 << 16);
OUTREG(R128_OV0_Y_X_END, x2 | y2 << 16);
OUTREG(R128_OV0_V_INC, vertInc);
OUTREG(R128_OV0_P1_BLANK_LINES_AT_TOP,
0x00000fff | ((buffer->height - 1) << 16));
OUTREG(R128_OV0_VID_BUF_PITCH0_VALUE, buffer->bytes_per_row);
int32 width = window->width;
left = 0;
OUTREG(R128_OV0_P1_X_START_END, (width - 1) | (left << 16));
width >>= 1;
OUTREG(R128_OV0_P2_X_START_END, (width - 1) | (left << 16));
OUTREG(R128_OV0_P3_X_START_END, (width - 1) | (left << 16));
OUTREG(R128_OV0_VID_BUF0_BASE_ADRS, offset);
OUTREG(R128_OV0_P1_V_ACCUM_INIT, p1_v_accum_init);
OUTREG(R128_OV0_P23_V_ACCUM_INIT, 0);
OUTREG(R128_OV0_P1_H_ACCUM_INIT, p1_h_accum_init);
OUTREG(R128_OV0_P23_H_ACCUM_INIT, p23_h_accum_init);
OUTREG(R128_OV0_SCALE_CNTL, 0x41FF8B03);
OUTREG(R128_OV0_REG_LOAD_CNTL, 0);
return true;
}
void
Rage128_StopOverlay(void)
{
OUTREG(R128_OV0_SCALE_CNTL, 0);
sCurrentKeyColor = 0;
sCurrentKeyMask = 0;
}