Should have been part of r42335.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42336 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
124cdd4f57
commit
43ad8a3327
145
src/add-ons/accelerants/ati/mach64_overlay.cpp
Normal file
145
src/add-ons/accelerants/ati/mach64_overlay.cpp
Normal file
@ -0,0 +1,145 @@
|
||||
/*
|
||||
Haiku ATI video driver adapted from the X.org ATI driver which has the
|
||||
following copyright:
|
||||
|
||||
Copyright 2003 through 2004 by Marc Aurele La France, tsi@xfree86.org
|
||||
|
||||
Copyright 2011 Haiku, Inc. All rights reserved.
|
||||
Distributed under the terms of the MIT license.
|
||||
|
||||
Authors:
|
||||
Gerald Zajac
|
||||
*/
|
||||
|
||||
#include "accelerant.h"
|
||||
#include "mach64.h"
|
||||
|
||||
|
||||
|
||||
bool
|
||||
Mach64_DisplayOverlay(const overlay_window* window,
|
||||
const overlay_buffer* buffer)
|
||||
{
|
||||
// Return true if setup is successful.
|
||||
|
||||
SharedInfo& si = *gInfo.sharedInfo;
|
||||
|
||||
if (window == NULL || buffer == NULL)
|
||||
return false;
|
||||
|
||||
uint32 videoFormat;
|
||||
|
||||
if (buffer->space == B_YCbCr422)
|
||||
videoFormat = SCALE_IN_VYUY422;
|
||||
else
|
||||
return false; // color space not supported
|
||||
|
||||
int32 x1 = (window->h_start < 0) ? 0 : window->h_start;
|
||||
int32 y1 = (window->v_start < 0) ? 0 : window->v_start;
|
||||
|
||||
int32 x2 = window->h_start + window->width - 1;
|
||||
int32 y2 = window->v_start + window->height - 1;
|
||||
|
||||
if (x2 > si.displayMode.timing.h_display)
|
||||
x2 = si.displayMode.timing.h_display;
|
||||
|
||||
if (y2 > si.displayMode.timing.v_display)
|
||||
y2 = si.displayMode.timing.v_display;
|
||||
|
||||
// If window is moved beyond edge of screen, do not allow width < 4 or
|
||||
// height < 4; otherwise there is a possibilty of divide by zero when
|
||||
// computing the scale factors..
|
||||
if (x2 < x1 + 4)
|
||||
x2 = x1 + 4;
|
||||
|
||||
if (y2 < y1 + 4)
|
||||
y2 = y1 + 4;
|
||||
|
||||
// Calculate overlay scale factors.
|
||||
uint32 horzScale = (buffer->width << 12) / (x2 - x1 + 1);
|
||||
uint32 vertScale = (buffer->height << 12) / (y2 - y1 + 1);
|
||||
|
||||
if (horzScale > 0xffff) // only 16 bits are used for scale factors
|
||||
horzScale = 0xffff;
|
||||
if (vertScale > 0xffff)
|
||||
vertScale = 0xffff;
|
||||
|
||||
gInfo.WaitForFifo(2);
|
||||
OUTREG(BUS_CNTL, INREG(BUS_CNTL) | BUS_EXT_REG_EN); // enable reg block 1
|
||||
OUTREG(OVERLAY_SCALE_CNTL, SCALE_EN); // reset the video
|
||||
|
||||
if (si.chipType >= MACH64_264GTPRO) {
|
||||
const uint32 brightness = 0;
|
||||
const uint32 saturation = 12;
|
||||
|
||||
gInfo.WaitForFifo(6);
|
||||
OUTREG(SCALER_COLOUR_CNTL, brightness | saturation << 8
|
||||
| saturation << 16);
|
||||
OUTREG(SCALER_H_COEFF0, 0x0002000);
|
||||
OUTREG(SCALER_H_COEFF1, 0xd06200d);
|
||||
OUTREG(SCALER_H_COEFF2, 0xd0a1c0d);
|
||||
OUTREG(SCALER_H_COEFF3, 0xc0e1a0c);
|
||||
OUTREG(SCALER_H_COEFF4, 0xc14140c);
|
||||
}
|
||||
|
||||
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;
|
||||
// 15 bit color has no alpha bits
|
||||
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;
|
||||
// 16 bit color has no alpha bits
|
||||
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;
|
||||
}
|
||||
|
||||
gInfo.WaitForFifo(3);
|
||||
OUTREG(OVERLAY_GRAPHICS_KEY_MSK, keyMask);
|
||||
OUTREG(OVERLAY_GRAPHICS_KEY_CLR, keyColor);
|
||||
OUTREG(OVERLAY_KEY_CNTL, OVERLAY_MIX_FALSE | OVERLAY_MIX_EQUAL);
|
||||
|
||||
gInfo.WaitForFifo(8);
|
||||
OUTREG(OVERLAY_Y_X_START, OVERLAY_LOCK_START | (x1 << 16) | y1);
|
||||
OUTREG(OVERLAY_Y_X_END, (x2 << 16) | y2);
|
||||
OUTREG(OVERLAY_SCALE_INC, (horzScale << 16) | vertScale);
|
||||
OUTREG(SCALER_HEIGHT_WIDTH, (buffer->width << 16) | buffer->height);
|
||||
OUTREG(VIDEO_FORMAT, videoFormat);
|
||||
|
||||
// Compute offset of overlay buffer in the video memory.
|
||||
uint32 offset = uint32(buffer->buffer) - si.videoMemAddr;
|
||||
|
||||
if (si.chipType < MACH64_264VTB) {
|
||||
OUTREG(BUF0_OFFSET, offset);
|
||||
OUTREG(BUF0_PITCH, buffer->width);
|
||||
} else {
|
||||
OUTREG(SCALER_BUF0_OFFSET, offset);
|
||||
OUTREG(SCALER_BUF0_PITCH, buffer->width);
|
||||
}
|
||||
|
||||
OUTREG(OVERLAY_SCALE_CNTL, SCALE_PIX_EXPAND | OVERLAY_EN | SCALE_EN);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Mach64_StopOverlay(void)
|
||||
{
|
||||
OUTREG(OVERLAY_SCALE_CNTL, SCALE_EN); // reset the video
|
||||
}
|
319
src/add-ons/accelerants/ati/overlay.cpp
Normal file
319
src/add-ons/accelerants/ati/overlay.cpp
Normal file
@ -0,0 +1,319 @@
|
||||
/*
|
||||
Copyright 2011 Haiku, Inc. All rights reserved.
|
||||
Distributed under the terms of the MIT license.
|
||||
|
||||
Authors:
|
||||
Gerald Zajac
|
||||
*/
|
||||
|
||||
#include "accelerant.h"
|
||||
#include "rage128.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
|
||||
uint32
|
||||
OverlayCount(const display_mode* mode)
|
||||
{
|
||||
(void)mode; // avoid compiler warning for unused arg
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
const uint32*
|
||||
OverlaySupportedSpaces(const display_mode* mode)
|
||||
{
|
||||
(void)mode; // avoid compiler warning for unused arg
|
||||
|
||||
static const uint32 kSupportedSpaces[] = {B_YCbCr422, 0};
|
||||
|
||||
return kSupportedSpaces;
|
||||
}
|
||||
|
||||
|
||||
uint32
|
||||
OverlaySupportedFeatures(uint32 colorSpace)
|
||||
{
|
||||
(void)colorSpace; // avoid compiler warning for unused arg
|
||||
|
||||
return B_OVERLAY_COLOR_KEY
|
||||
| B_OVERLAY_HORIZONTAL_FILTERING
|
||||
| B_OVERLAY_VERTICAL_FILTERING;
|
||||
}
|
||||
|
||||
|
||||
const overlay_buffer*
|
||||
AllocateOverlayBuffer(color_space colorSpace, uint16 width, uint16 height)
|
||||
{
|
||||
SharedInfo& si = *gInfo.sharedInfo;
|
||||
|
||||
TRACE("AllocateOverlayBuffer() width %u, height %u, colorSpace 0x%lx\n",
|
||||
width, height, colorSpace);
|
||||
|
||||
// If Mach 64 chip, check hardware limits.
|
||||
|
||||
if (MACH64_FAMILY(si.chipType)) {
|
||||
if (height > 2048 || width > 768
|
||||
|| (width > 384 && si.chipType < MACH64_264VTB)
|
||||
|| (width > 720 && (si.chipType < MACH64_264GTPRO
|
||||
|| si.chipType > MACH64_264LTPRO)))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
si.overlayLock.Acquire();
|
||||
|
||||
// Note: When allocating buffers, buffer allocation starts at the end of
|
||||
// video memory, and works backward to the end of the video frame buffer.
|
||||
// The allocated buffers are recorded in a linked list of OverlayBuffer
|
||||
// objects which are ordered by the buffer address with the first object
|
||||
// in the list having the highest buffer address.
|
||||
|
||||
if (colorSpace != B_YCbCr422) {
|
||||
si.overlayLock.Release();
|
||||
TRACE("AllocateOverlayBuffer() unsupported color space 0x%x\n",
|
||||
colorSpace);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32 bytesPerPixel = 2; // B_YCbCr422 uses 2 bytes per pixel
|
||||
|
||||
// Calculate required buffer size as a multiple of 1K.
|
||||
uint32 buffSize = (width * bytesPerPixel * height + 0x3ff) & ~0x3ff;
|
||||
|
||||
OverlayBuffer* ovBuff = si.overlayBuffer;
|
||||
OverlayBuffer* prevOvBuff = NULL;
|
||||
|
||||
// If no buffers have been allocated, prevBuffAddr calculated here will be
|
||||
// the address where the buffer area will start. Leave a gap of about 4K
|
||||
// between where the overlay buffers will start and the cursor image;
|
||||
// thus, if the overlay buffer overflows it will be less apt to affect the
|
||||
// cursor.
|
||||
|
||||
uint32 prevBuffAddr = (si.videoMemAddr + si.cursorOffset - 0xfff) & ~0xfff;
|
||||
|
||||
while (ovBuff != NULL) {
|
||||
// Test if there is sufficient space between the end of the current
|
||||
// buffer and the start of the previous buffer to allocate the new
|
||||
// buffer.
|
||||
|
||||
uint32 currentBuffEndAddr = (addr_t)ovBuff->buffer + ovBuff->size;
|
||||
if ((prevBuffAddr - currentBuffEndAddr) >= buffSize)
|
||||
break; // sufficient space for the new buffer
|
||||
|
||||
prevBuffAddr = (uint32)ovBuff->buffer;
|
||||
prevOvBuff = ovBuff;
|
||||
ovBuff = ovBuff->nextBuffer;
|
||||
}
|
||||
|
||||
OverlayBuffer* nextOvBuff = ovBuff;
|
||||
|
||||
if (ovBuff == NULL) {
|
||||
// No space between any current buffers of the required size was found;
|
||||
// thus space must be allocated between the last buffer and the end of
|
||||
// the video frame buffer. Compute where current video frame buffer
|
||||
// ends so that it can be determined if there is sufficient space for
|
||||
// the new buffer to be created.
|
||||
|
||||
uint32 fbEndAddr = si.videoMemAddr + si.frameBufferOffset
|
||||
+ (si.displayMode.virtual_width
|
||||
* ((si.displayMode.bitsPerPixel + 7) / 8) // bytes per pixel
|
||||
* si.displayMode.virtual_height);
|
||||
|
||||
if (buffSize > prevBuffAddr - fbEndAddr) {
|
||||
si.overlayLock.Release();
|
||||
TRACE("AllocateOverlayBuffer() insuffcient space for %ld (0x%lx) "
|
||||
"byte buffer\n", buffSize, buffSize);
|
||||
return NULL; // insufficient space for buffer
|
||||
}
|
||||
|
||||
nextOvBuff = NULL;
|
||||
}
|
||||
|
||||
ovBuff = (OverlayBuffer*)malloc(sizeof(OverlayBuffer));
|
||||
if (ovBuff == NULL) {
|
||||
si.overlayLock.Release();
|
||||
return NULL; // memory not available for OverlayBuffer struct
|
||||
}
|
||||
|
||||
ovBuff->nextBuffer = nextOvBuff;
|
||||
ovBuff->size = buffSize;
|
||||
ovBuff->space = colorSpace;
|
||||
ovBuff->width = width;
|
||||
ovBuff->height = height;
|
||||
ovBuff->bytes_per_row = width * bytesPerPixel;
|
||||
ovBuff->buffer = (void*)(prevBuffAddr - buffSize);
|
||||
ovBuff->buffer_dma = (void*)(si.videoMemPCI
|
||||
+ ((addr_t)ovBuff->buffer - si.videoMemAddr));
|
||||
|
||||
if (prevOvBuff == NULL)
|
||||
si.overlayBuffer = ovBuff;
|
||||
else
|
||||
prevOvBuff->nextBuffer = ovBuff;
|
||||
|
||||
si.overlayLock.Release();
|
||||
TRACE("AllocateOverlayBuffer() allocated %ld (0x%lx) byte buffer at 0x%lx\n",
|
||||
buffSize, buffSize, ovBuff->buffer);
|
||||
return ovBuff;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ReleaseOverlayBuffer(const overlay_buffer* buffer)
|
||||
{
|
||||
SharedInfo& si = *gInfo.sharedInfo;
|
||||
|
||||
if (buffer == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
// Find the buffer to be released.
|
||||
|
||||
OverlayBuffer* ovBuff = si.overlayBuffer;
|
||||
OverlayBuffer* prevOvBuff = NULL;
|
||||
|
||||
while (ovBuff != NULL) {
|
||||
if (ovBuff->buffer == buffer->buffer) {
|
||||
// Buffer to be released has been found. Remove the OverlayBuffer
|
||||
// object from the chain of overlay buffers.
|
||||
|
||||
if (prevOvBuff == NULL)
|
||||
si.overlayBuffer = ovBuff->nextBuffer;
|
||||
else
|
||||
prevOvBuff->nextBuffer = ovBuff->nextBuffer;
|
||||
|
||||
free(ovBuff);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
prevOvBuff = ovBuff;
|
||||
ovBuff = ovBuff->nextBuffer;
|
||||
}
|
||||
|
||||
TRACE("ReleaseOverlayBuffer() buffer to release at 0x%lx not found\n",
|
||||
buffer->buffer);
|
||||
return B_ERROR; // buffer to be released not found in chain of buffers
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
GetOverlayConstraints(const display_mode* mode, const overlay_buffer* buffer,
|
||||
overlay_constraints* constraints)
|
||||
{
|
||||
if ((mode == NULL) || (buffer == NULL) || (constraints == NULL))
|
||||
return B_ERROR;
|
||||
|
||||
// Position (values are in pixels)
|
||||
constraints->view.h_alignment = 0;
|
||||
constraints->view.v_alignment = 0;
|
||||
|
||||
if (buffer->space == B_YCbCr422)
|
||||
constraints->view.width_alignment = 7;
|
||||
else {
|
||||
TRACE("GetOverlayConstraints() color space 0x%x out of range\n",
|
||||
buffer->space);
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
constraints->view.height_alignment = 0;
|
||||
|
||||
//Size
|
||||
constraints->view.width.min = 4;
|
||||
constraints->view.height.min = 4;
|
||||
constraints->view.width.max = buffer->width;
|
||||
constraints->view.height.max = buffer->height;
|
||||
|
||||
// Scaler output restrictions
|
||||
constraints->window.h_alignment = 0;
|
||||
constraints->window.v_alignment = 0;
|
||||
constraints->window.width_alignment = 0;
|
||||
constraints->window.height_alignment = 0;
|
||||
constraints->window.width.min = 2;
|
||||
constraints->window.width.max = mode->virtual_width;
|
||||
constraints->window.height.min = 2;
|
||||
constraints->window.height.max = mode->virtual_height;
|
||||
|
||||
constraints->h_scale.min = 1.0;
|
||||
constraints->h_scale.max = 8.0;
|
||||
constraints->v_scale.min = 1.0;
|
||||
constraints->v_scale.max = 8.0;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
overlay_token
|
||||
AllocateOverlay(void)
|
||||
{
|
||||
SharedInfo& si = *gInfo.sharedInfo;
|
||||
|
||||
// There is only a single overlay channel; thus, check if it is already
|
||||
// allocated.
|
||||
|
||||
if (atomic_or(&si.overlayAllocated, 1) != 0) {
|
||||
TRACE("AllocateOverlay() overlay channel already in use\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (overlay_token)++si.overlayToken;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ReleaseOverlay(overlay_token overlayToken)
|
||||
{
|
||||
SharedInfo& si = *gInfo.sharedInfo;
|
||||
|
||||
if (overlayToken != (overlay_token)si.overlayToken) {
|
||||
TRACE("ReleaseOverlay() error - no overlay previously allocated\n");
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
if (MACH64_FAMILY(si.chipType))
|
||||
Mach64_StopOverlay();
|
||||
else
|
||||
Rage128_StopOverlay();
|
||||
|
||||
atomic_and(&si.overlayAllocated, 0); // mark overlay as unallocated
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ConfigureOverlay(overlay_token overlayToken, const overlay_buffer* buffer,
|
||||
const overlay_window* window, const overlay_view* view)
|
||||
{
|
||||
SharedInfo& si = *gInfo.sharedInfo;
|
||||
|
||||
if (overlayToken != (overlay_token)si.overlayToken)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
if (buffer == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
if (window == NULL || view == NULL) {
|
||||
if (MACH64_FAMILY(si.chipType))
|
||||
Mach64_StopOverlay();
|
||||
else
|
||||
Rage128_StopOverlay();
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
// Program the overlay hardware.
|
||||
if (MACH64_FAMILY(si.chipType)) {
|
||||
if (!Mach64_DisplayOverlay(window, buffer)) {
|
||||
TRACE("ConfigureOverlay(), call to Mach64_DisplayOverlay() "
|
||||
"returned error\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
} else {
|
||||
if (!Rage128_DisplayOverlay(window, buffer)) {
|
||||
TRACE("ConfigureOverlay(), call to Rage128_DisplayOverlay() "
|
||||
"returned error\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
178
src/add-ons/accelerants/ati/rage128_overlay.cpp
Normal file
178
src/add-ons/accelerants/ati/rage128_overlay.cpp
Normal file
@ -0,0 +1,178 @@
|
||||
/*
|
||||
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)
|
||||
{
|
||||
// Return true if setup is successful.
|
||||
|
||||
SharedInfo& si = *gInfo.sharedInfo;
|
||||
|
||||
if (window == NULL || buffer == NULL)
|
||||
return false;
|
||||
|
||||
if (buffer->space != B_YCbCr422)
|
||||
return false; // color space not supported
|
||||
|
||||
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;
|
||||
// 15 bit color has no alpha bits
|
||||
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;
|
||||
// 16 bit color has no alpha bits
|
||||
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 the key color or key mask has changed since the overlay was
|
||||
// previously initialized, initialize it again. This is to avoid
|
||||
// initializing the overlay video everytime the overlay buffer is
|
||||
// switched which causes artifacts in the overlay display.
|
||||
|
||||
if (keyColor != sCurrentKeyColor || keyMask != sCurrentKeyMask)
|
||||
{
|
||||
TRACE("Rage128_DisplayOverlay() initializing overlay video\n");
|
||||
|
||||
// Initialize the overlay video by first resetting the video.
|
||||
|
||||
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;
|
||||
|
||||
// Compute offset of overlay buffer in the video memory.
|
||||
uint32 offset = uint32(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); // reset the video
|
||||
|
||||
// Reset the key color and mask so that when the overlay is started again
|
||||
// it will be initialized.
|
||||
|
||||
sCurrentKeyColor = 0;
|
||||
sCurrentKeyMask = 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user