Index: headers/private/graphics/ati/DriverInterface.h
===================================================================
--- headers/private/graphics/ati/DriverInterface.h	(revision 42305)
+++ headers/private/graphics/ati/DriverInterface.h	(working copy)
@@ -1,9 +1,9 @@
 /*
-	Copyright 2007-2009 Haiku, Inc.  All rights reserved.
+	Copyright 2007-2011 Haiku, Inc.  All rights reserved.
 	Distributed under the terms of the MIT license.
 
 	Authors:
-	Gerald Zajac 2007-2009
+	Gerald Zajac
 */
 
 #ifndef DRIVERINTERFACE_H
@@ -14,6 +14,7 @@
 #include <GraphicsDefs.h>
 #include <Drivers.h>
 #include <edid.h>
+#include <video_overlay.h>
 
 
 // This file contains info that is shared between the kernel driver and the
@@ -163,6 +164,12 @@
 };
 
 
+struct OverlayBuffer : overlay_buffer {
+	OverlayBuffer*	nextBuffer;	// pointer to next buffer in chain, NULL = none
+	uint32			size;		// size of overlay buffer
+};
+
+
 struct SharedInfo {
 	// Device ID info.
 	uint16	vendorID;			// PCI vendor ID, from pci_info
@@ -180,8 +187,8 @@
 	area_id regsArea;			// area_id for the memory mapped registers. It will
 								// be cloned into accelerant's address space.
 	area_id videoMemArea;		// video memory area_id.  The addresses are shared with all teams.
-	void*	videoMemAddr;		// video memory addr as viewed from virtual memory
-	void*	videoMemPCI;		// video memory addr as viewed from the PCI bus (for DMA)
+	addr_t	videoMemAddr;		// video memory addr as viewed from virtual memory
+	phys_addr_t	videoMemPCI;	// video memory addr as viewed from the PCI bus (for DMA)
 	uint32	videoMemSize; 		// video memory size in bytes.
 
 	uint32	cursorOffset;		// offset of cursor in video memory
@@ -209,7 +216,12 @@
 	bool		bHaveEDID;		// true = EDID info from device is in edidInfo
 
 	Benaphore	engineLock;		// for serializing access to the acceleration engine
+	Benaphore	overlayLock;	// for overlay operations
 
+	int32		overlayAllocated;	// non-zero if overlay is allocated
+	uint32		overlayToken;
+	OverlayBuffer* overlayBuffer;	// pointer to linked list of buffers; NULL = none
+
 	MonitorType	displayType;
 
 	uint16		panelX;			// laptop LCD width
@@ -227,7 +239,7 @@
 	R128_RAMSpec	r128MemSpec;	// Rage128 memory timing spec's
 	R128_PLLParams	r128PLLParams;	// Rage128 PLL parameters from video BIOS ROM
 
-	uint32			r128_dpGuiMasterCntl;	// flags for accelerated drawing
+	uint32		r128_dpGuiMasterCntl;	// flags for accelerated drawing
 };
 
 
Index: src/add-ons/kernel/drivers/graphics/ati/driver.cpp
===================================================================
--- src/add-ons/kernel/drivers/graphics/ati/driver.cpp	(revision 42305)
+++ src/add-ons/kernel/drivers/graphics/ati/driver.cpp	(working copy)
@@ -1,9 +1,9 @@
 /*
-	Copyright 2007-2009 Haiku, Inc.  All rights reserved.
+	Copyright 2007-2011 Haiku, Inc.  All rights reserved.
 	Distributed under the terms of the MIT license.
 
 	Authors:
-	Gerald Zajac 2007-2009
+	Gerald Zajac
 */
 
 #include <KernelExport.h>
@@ -20,7 +20,6 @@
 
 #undef TRACE
 
-//#define ENABLE_DEBUG_TRACE
 #ifdef ENABLE_DEBUG_TRACE
 #	define TRACE(x...) dprintf("ati: " x)
 #else
@@ -41,7 +40,7 @@
 #define M64_BIOS_SIZE		0x10000		// 64KB
 #define R128_BIOS_SIZE		0x10000		// 64KB
 
-int32 api_version = B_CUR_DRIVER_API_VERSION;	// revision of driver API we support
+int32 api_version = B_CUR_DRIVER_API_VERSION;	// revision of driver API used
 
 #define VENDOR_ID 0x1002	// ATI vendor ID
 
@@ -54,7 +53,8 @@
 struct ChipInfo {
 	uint16		chipID;			// PCI device id of the chip
 	ChipType	chipType;		// assigned chip type identifier
-	const char*	chipName;		// user recognizable name for chip (must be < 32 chars)
+	const char*	chipName;		// user recognizable name for chip
+								//   (must be < 32 chars)
 };
 
 
@@ -199,14 +199,16 @@
 static inline uint32
 GetPCI(pci_info& info, uint8 offset, uint8 size)
 {
-	return gPCI->read_pci_config(info.bus, info.device, info.function, offset, size);
+	return gPCI->read_pci_config(info.bus, info.device, info.function, offset,
+		size);
 }
 
 
 static inline void
 SetPCI(pci_info& info, uint8 offset, uint8 size, uint32 value)
 {
-	gPCI->write_pci_config(info.bus, info.device, info.function, offset, size, value);
+	gPCI->write_pci_config(info.bus, info.device, info.function, offset, size,
+		value);
 }
 
 
@@ -251,7 +253,8 @@
 
 	status_t status = vm86_prepare(&vmState, 0x2000);
 	if (status != B_OK) {
-		TRACE("GetEdidFromBIOS(); vm86_prepare() failed, status: 0x%lx\n", status);
+		TRACE("GetEdidFromBIOS(); vm86_prepare() failed, status: 0x%lx\n",
+			status);
 		return status;
 	}
 
@@ -337,7 +340,8 @@
 
 	status_t status = vm86_prepare(&vmState, 0x2000);
 	if (status != B_OK) {
-		TRACE("SetVesaDisplayMode(); vm86_prepare() failed, status: 0x%lx\n", status);
+		TRACE("SetVesaDisplayMode(); vm86_prepare() failed, status: 0x%lx\n",
+			status);
 		return status;
 	}
 
@@ -505,8 +509,9 @@
 	pll.max_pll_freq = BIOS32(pllInfoBlock + 0x16);
 	pll.xclk = BIOS16(pllInfoBlock + 0x08);
 
-	TRACE("PLL parameters: rf=%d rd=%d min=%ld max=%ld; xclk=%d\n", pll.reference_freq,
-		pll.reference_div, pll.min_pll_freq, pll.max_pll_freq, pll.xclk);
+	TRACE("PLL parameters: rf=%d rd=%d min=%ld max=%ld; xclk=%d\n",
+		pll.reference_freq, pll.reference_div, pll.min_pll_freq,
+		pll.max_pll_freq, pll.xclk);
 
 	// If Mobility chip, get the LCD panel width & height and a few other
 	// related parameters.
@@ -537,7 +542,8 @@
 						si.panelY = BIOS16(fpStart + 27);
 						si.panelPowerDelay = BIOS8(fpStart + 56);
 						TRACE("LCD Panel size: %dx%d  Panel type: 0x%x   power delay: %d\n",
-							si.panelX, si.panelY, BIOS16(fpStart + 29), si.panelPowerDelay);
+							si.panelX, si.panelY, BIOS16(fpStart + 29),
+							si.panelPowerDelay);
 						break;
 					}
 				}
@@ -566,9 +572,9 @@
 
 	// Map the video memory.
 
-	uint32 videoRamAddr = pciInfo.u.h0.base_registers[0];
+	phys_addr_t videoRamAddr = pciInfo.u.h0.base_registers[0];
 	uint32 videoRamSize = pciInfo.u.h0.base_register_sizes[0];
-	si.videoMemPCI = (void *)videoRamAddr;
+	si.videoMemPCI = videoRamAddr;
 	char frameBufferAreaName[] = "ATI frame buffer";
 
 	si.videoMemArea = map_physical_memory(
@@ -577,7 +583,7 @@
 		videoRamSize,
 		B_ANY_KERNEL_BLOCK_ADDRESS | B_MTR_WC,
 		B_READ_AREA + B_WRITE_AREA,
-		&(si.videoMemAddr));
+		(void**)&(si.videoMemAddr));
 
 	if (si.videoMemArea < 0) {
 		// Try to map this time without write combining.
@@ -587,7 +593,7 @@
 			videoRamSize,
 			B_ANY_KERNEL_BLOCK_ADDRESS,
 			B_READ_AREA + B_WRITE_AREA,
-			&(si.videoMemAddr));
+			(void**)&(si.videoMemAddr));
 	}
 
 	if (si.videoMemArea < 0)
@@ -595,7 +601,7 @@
 
 	// Map the MMIO register area.
 
-	uint32 regsBase = pciInfo.u.h0.base_registers[2];
+	phys_addr_t regsBase = pciInfo.u.h0.base_registers[2];
 	uint32 regAreaSize = pciInfo.u.h0.base_register_sizes[2];
 
 	// If the register area address or size is not in the PCI info, it should
@@ -619,7 +625,8 @@
 
 		regsBase = videoRamAddr + regsOffset;
 		regAreaSize = 0x1000;
-		TRACE("Register address is at end of frame buffer memory at 0x%lx\n", regsBase);
+		TRACE("Register address is at end of frame buffer memory at 0x%lx\n",
+			uint32(regsBase));
 	}
 
 	si.regsArea = map_physical_memory("ATI mmio registers",
@@ -627,7 +634,7 @@
 		regAreaSize,
 		B_ANY_KERNEL_ADDRESS,
 		0,		// neither read nor write, to hide it from user space apps
-		(void**)(&(di.regs)));
+		(void**)&di.regs);
 
 	// If there was an error, delete other areas.
 	if (si.regsArea < 0) {
@@ -650,7 +657,7 @@
 		delete_area(si.videoMemArea);
 
 	si.regsArea = si.videoMemArea = -1;
-	si.videoMemAddr = NULL;
+	si.videoMemAddr = (addr_t)NULL;
 	di.regs = NULL;
 }
 
@@ -768,7 +775,8 @@
 		si.vesaModeTableOffset = sharedSize;
 		si.vesaModeCount = vesaModeTableSize / sizeof(VesaMode);
 
-		memcpy((uint8*)&si + si.vesaModeTableOffset, vesaModes, vesaModeTableSize);
+		memcpy((uint8*)&si + si.vesaModeTableOffset, vesaModes,
+			vesaModeTableSize);
 	}
 
 	pci_info& pciInfo = di.pciInfo;
@@ -892,7 +900,8 @@
 	pci_info pciInfo;
 	const ChipInfo* pDevice = GetNextSupportedDevice(pciIndex, pciInfo);
 
-	TRACE("init_hardware() - %s\n", pDevice == NULL ? "no supported devices" : "device supported");
+	TRACE("init_hardware() - %s\n",
+		pDevice == NULL ? "no supported devices" : "device supported");
 
 	put_module(B_PCI_MODULE_NAME);		// put away the module manager
 
@@ -900,7 +909,8 @@
 }
 
 
-status_t  init_driver(void)
+status_t
+init_driver(void)
 {
 	// Get handle for the pci bus.
 
@@ -1011,7 +1021,8 @@
 		*cookie = &di;		// send cookie to opener
 	}
 
-	TRACE("device_open() returning 0x%lx,  open count: %ld\n", status, di.openCount);
+	TRACE("device_open() returning 0x%lx,  open count: %ld\n", status,
+		di.openCount);
 	return status;
 }
 
@@ -1019,7 +1030,8 @@
 static status_t
 device_read(void* dev, off_t pos, void* buf, size_t* len)
 {
-	// Following 3 lines of code are here to eliminate "unused parameter" warnings.
+	// Following 3 lines of code are here to eliminate "unused parameter"
+	// warnings.
 	(void)dev;
 	(void)pos;
 	(void)buf;
@@ -1032,7 +1044,8 @@
 static status_t
 device_write(void* dev, off_t pos, const void* buf, size_t* len)
 {
-	// Following 3 lines of code are here to eliminate "unused parameter" warnings.
+	// Following 3 lines of code are here to eliminate "unused parameter"
+	// warnings.
 	(void)dev;
 	(void)pos;
 	(void)buf;
@@ -1068,10 +1081,12 @@
 		DisableVBI();		// disable & clear any pending interrupts
 
 		if (si.bInterruptAssigned) {
-			remove_io_interrupt_handler(pciInfo.u.h0.interrupt_line, InterruptHandler, &di);
+			remove_io_interrupt_handler(pciInfo.u.h0.interrupt_line,
+				InterruptHandler, &di);
 		}
 
-		// Delete the semaphores, ignoring any errors because the owning team may have died.
+		// Delete the semaphores, ignoring any errors because the owning team
+		// may have died.
 		if (si.vertBlankSem >= 0)
 			delete_sem(si.vertBlankSem);
 		si.vertBlankSem = -1;
@@ -1098,7 +1113,8 @@
 {
 	DeviceInfo& di = *((DeviceInfo*)dev);
 
-//	TRACE("device_ioctl(); ioctl: %lu, buffer: 0x%08lx, bufLen: %lu\n", msg, (uint32)buffer, bufferLength);
+//	TRACE("device_ioctl(); ioctl: %lu, buffer: 0x%08lx, bufLen: %lu\n", msg,
+//		(uint32)buffer, bufferLength);
 
 	switch (msg) {
 		case B_GET_ACCELERANT_SIGNATURE:
Index: src/add-ons/accelerants/ati/accelerant.h
===================================================================
--- src/add-ons/accelerants/ati/accelerant.h	(revision 42305)
+++ src/add-ons/accelerants/ati/accelerant.h	(working copy)
@@ -1,9 +1,9 @@
 /*
-	Copyright 2007-2009 Haiku, Inc.  All rights reserved.
+	Copyright 2007-2011 Haiku, Inc.  All rights reserved.
 	Distributed under the terms of the MIT license.
 
 	Authors:
-	Gerald Zajac 2007-2009
+	Gerald Zajac
 */
 
 #ifndef _ACCELERANT_H
@@ -52,22 +52,27 @@
 	status_t (*SetDPMSMode)(uint32 dpms_flags);
 
 	// Pointers to cursor functions.
-	bool	(*LoadCursorImage)(int width, int height, uint8* and_mask, uint8* xor_mask);
+	bool	(*LoadCursorImage)(int width, int height, uint8* and_mask,
+				uint8* xor_mask);
 	void	(*SetCursorPosition)(int x, int y);
 	void	(*ShowCursor)(bool bShow);
 
 	// Pointers to 2D acceleration functions.
-	void	(*FillRectangle)(engine_token*, uint32 color, fill_rect_params*, uint32 count);
-	void	(*FillSpan)(engine_token*, uint32 color, uint16* list, uint32 count);
+	void	(*FillRectangle)(engine_token*, uint32 color, fill_rect_params*,
+				uint32 count);
+	void	(*FillSpan)(engine_token*, uint32 color, uint16* list,
+				uint32 count);
 	void	(*InvertRectangle)(engine_token*, fill_rect_params*, uint32 count);
 	void	(*ScreenToScreenBlit)(engine_token*, blit_params*, uint32 count);
 
 	// Pointers to other functions.
 	void	 (*AdjustFrame)(const DisplayModeEx& mode);
 	status_t (*ChipInit)(void);
-	bool	 (*GetColorSpaceParams)(int colorSpace, uint8& bpp, uint32& maxPixelClk);
+	bool	 (*GetColorSpaceParams)(int colorSpace, uint8& bpp,
+				uint32& maxPixelClk);
 	status_t (*SetDisplayMode)(const DisplayModeEx& mode);
-	void	 (*SetIndexedColors)(uint count, uint8 first, uint8* color_data, uint32 flags);
+	void	 (*SetIndexedColors)(uint count, uint8 first, uint8* color_data,
+				uint32 flags);
 };
 
 extern AccelerantInfo gInfo;
@@ -95,15 +100,18 @@
 // Mode Configuration
 uint32	 AccelerantModeCount(void);
 status_t GetModeList(display_mode* dm);
-status_t ProposeDisplayMode(display_mode* target, const display_mode* low, const display_mode* high);
+status_t ProposeDisplayMode(display_mode* target, const display_mode* low,
+					const display_mode* high);
 status_t SetDisplayMode(display_mode* mode_to_set);
 status_t GetDisplayMode(display_mode* current_mode);
 status_t GetFrameBufferConfig(frame_buffer_config* a_frame_buffer);
 status_t GetPixelClockLimits(display_mode* dm, uint32* low, uint32* high);
 status_t MoveDisplay(uint16 h_display_start, uint16 v_display_start);
 status_t GetTimingConstraints(display_timing_constraints* dtc);
-void	 Mach64_SetIndexedColors(uint count, uint8 first, uint8* color_data, uint32 flags);
-void	 Rage128_SetIndexedColors(uint count, uint8 first, uint8* color_data, uint32 flags);
+void	 Mach64_SetIndexedColors(uint count, uint8 first, uint8* color_data,
+					uint32 flags);
+void	 Rage128_SetIndexedColors(uint count, uint8 first, uint8* color_data,
+					uint32 flags);
 status_t GetPreferredDisplayMode(display_mode* preferredMode);
 status_t GetEdidInfo(void* info, size_t size, uint32* _version);
 
@@ -118,28 +126,51 @@
 
 // Cursor
 status_t SetCursorShape(uint16 width, uint16 height, uint16 hot_x, uint16 hot_y,
-						uint8* andMask, uint8* xorMask);
+					uint8* andMask, uint8* xorMask);
 void	 MoveCursor(uint16 x, uint16 y);
 
 // Engine Management
 uint32   AccelerantEngineCount(void);
-status_t AcquireEngine(uint32 capabilities, uint32 max_wait, sync_token* st, engine_token** et);
+status_t AcquireEngine(uint32 capabilities, uint32 max_wait, sync_token* st,
+					engine_token** et);
 status_t ReleaseEngine(engine_token* et, sync_token* st);
 void	 WaitEngineIdle(void);
 status_t GetSyncToken(engine_token* et, sync_token* st);
 status_t SyncToToken(sync_token* st);
 
 // 2D acceleration
-void	 Mach64_FillRectangle(engine_token* et, uint32 color, fill_rect_params* list, uint32 count);
-void	 Mach64_FillSpan(engine_token* et, uint32 color, uint16* list, uint32 count);
-void	 Mach64_InvertRectangle(engine_token* et, fill_rect_params* list, uint32 count);
-void	 Mach64_ScreenToScreenBlit(engine_token* et, blit_params* list, uint32 count);
+void	 Mach64_FillRectangle(engine_token* et, uint32 color,
+					fill_rect_params* list, uint32 count);
+void	 Mach64_FillSpan(engine_token* et, uint32 color, uint16* list,
+					uint32 count);
+void	 Mach64_InvertRectangle(engine_token* et, fill_rect_params* list,
+					uint32 count);
+void	 Mach64_ScreenToScreenBlit(engine_token* et, blit_params* list,
+					uint32 count);
 
-void	 Rage128_FillRectangle(engine_token* et, uint32 color, fill_rect_params* list, uint32 count);
-void	 Rage128_FillSpan(engine_token* et, uint32 color, uint16* list, uint32 count);
-void	 Rage128_InvertRectangle(engine_token* et, fill_rect_params* list, uint32 count);
-void	 Rage128_ScreenToScreenBlit(engine_token* et, blit_params* list, uint32 count);
+void	 Rage128_FillRectangle(engine_token* et, uint32 color,
+					fill_rect_params* list, uint32 count);
+void	 Rage128_FillSpan(engine_token* et, uint32 color, uint16* list,
+					uint32 count);
+void	 Rage128_InvertRectangle(engine_token* et, fill_rect_params* list,
+					uint32 count);
+void	 Rage128_ScreenToScreenBlit(engine_token* et, blit_params* list,
+					uint32 count);
 
+// Video_overlay
+uint32		OverlayCount(const display_mode* dm);
+const uint32* OverlaySupportedSpaces(const display_mode* dm);
+uint32		OverlaySupportedFeatures(uint32 a_color_space);
+const overlay_buffer* AllocateOverlayBuffer(color_space cs, uint16 width,
+					uint16 height);
+status_t	ReleaseOverlayBuffer(const overlay_buffer* ob);
+status_t	GetOverlayConstraints(const display_mode* dm,
+					const overlay_buffer* ob, overlay_constraints* oc);
+overlay_token AllocateOverlay(void);
+status_t	ReleaseOverlay(overlay_token ot);
+status_t	ConfigureOverlay(overlay_token ot, const overlay_buffer* ob,
+					const overlay_window* ow, const overlay_view* ov);
+
 #if defined(__cplusplus)
 }
 #endif
@@ -156,10 +187,15 @@
 
 // Mach64 functions.
 
+bool	 Mach64_DisplayOverlay(const overlay_window* window,
+				const overlay_buffer* buffer);
+void	 Mach64_StopOverlay(void);
+
 void	 Mach64_EngineReset(void);
 void	 Mach64_EngineInit(const DisplayModeEx& mode);
 
-bool	 Mach64_LoadCursorImage(int width, int height, uint8* and_mask, uint8* xor_mask);
+bool	 Mach64_LoadCursorImage(int width, int height, uint8* and_mask,
+				uint8* xor_mask);
 void	 Mach64_SetCursorPosition(int x, int y);
 void	 Mach64_ShowCursor(bool bShow);
 
@@ -167,19 +203,25 @@
 status_t Mach64_SetDisplayMode(const DisplayModeEx& mode);
 void	 Mach64_SetFunctionPointers(void);
 
-int		 Mach64_Divide(int numerator, int denom, int shift, const int roundingKind);
-void	 Mach64_ReduceRatio(int *numerator, int *denominator);
+int		 Mach64_Divide(int numerator, int denom, int shift,
+				const int roundingKind);
+void	 Mach64_ReduceRatio(int* numerator, int* denominator);
 
 
 // Rage128 functions.
 
+bool	 Rage128_DisplayOverlay(const overlay_window* window,
+				const overlay_buffer* buffer);
+void	 Rage128_StopOverlay(void);
+
 void	 Rage128_EngineFlush(void);
 void	 Rage128_EngineReset(void);
 void	 Rage128_EngineInit(const DisplayModeEx& mode);
 
 bool	 Rage128_GetEdidInfo(void);
 
-bool	 Rage128_LoadCursorImage(int width, int height, uint8* and_mask, uint8* xor_mask);
+bool	 Rage128_LoadCursorImage(int width, int height, uint8* and_mask,
+				uint8* xor_mask);
 void	 Rage128_SetCursorPosition(int x, int y);
 void	 Rage128_ShowCursor(bool bShow);
 
Index: src/add-ons/accelerants/ati/rage128_overlay.cpp
===================================================================
--- src/add-ons/accelerants/ati/rage128_overlay.cpp	(revision 0)
+++ src/add-ons/accelerants/ati/rage128_overlay.cpp	(revision 0)
@@ -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;
+}
Index: src/add-ons/accelerants/ati/rage128.h
===================================================================
--- src/add-ons/accelerants/ati/rage128.h	(revision 42305)
+++ src/add-ons/accelerants/ati/rage128.h	(working copy)
@@ -1,15 +1,16 @@
 /*
-	Haiku ATI video driver adapted from the X.org ATI driver.
+	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 2009 Haiku, Inc.  All rights reserved.
+	Copyright 2009, 2011 Haiku, Inc.  All rights reserved.
 	Distributed under the terms of the MIT license.
 
 	Authors:
-	Gerald Zajac 2009
+	Gerald Zajac
 */
 
 
@@ -17,7 +18,7 @@
 #define __RAGE128_H__
 
 
-#define CURSOR_BYTES	1024		// bytes used for cursor image in video memory
+#define CURSOR_BYTES	1024	// bytes used for cursor image in video memory
 
 #define R128_TIMEOUT	2000000	// Fall out of wait loops after this count
 
@@ -203,7 +204,6 @@
 #define R128_OVR_CLR					  0x0230
 #define R128_OVR_WID_LEFT_RIGHT 		  0x0234
 #define R128_OVR_WID_TOP_BOTTOM 		  0x0238
-#define R128_OV0_SCALE_CNTL 			  0x0420
 
 #define R128_PALETTE_DATA				  0x00b4
 #define R128_PALETTE_INDEX				  0x00b0
@@ -231,14 +231,47 @@
 
 #define R128_TMDS_CRC                     0x02a0
 
-#define R128_VCLK_ECP_CNTL				  0x0008	// PLL
-#		define R128_VCLK_SRC_SEL_MASK	  0x03
-#		define R128_VCLK_SRC_SEL_CPUCLK   0x00
-#		define R128_VCLK_SRC_SEL_PPLLCLK  0x03
+#define R128_VCLK_ECP_CNTL				 0x0008	// PLL
+#		define R128_VCLK_SRC_SEL_MASK	 0x03
+#		define R128_VCLK_SRC_SEL_CPUCLK  0x00
+#		define R128_VCLK_SRC_SEL_PPLLCLK 0x03
+#		define R128_ECP_DIV_MASK		 (3 << 8)
 #define R128_VIPH_CONTROL				  0x01D0	// ?
 
 
+// Definitions used for overlays.
+//===============================
 
+#define R128_OV0_Y_X_START				0x0400
+#define R128_OV0_Y_X_END				0x0404
+#define R128_OV0_EXCLUSIVE_HORZ 		0x0408
+#define R128_OV0_REG_LOAD_CNTL			0x0410
+#define R128_OV0_SCALE_CNTL 			0x0420
+#define R128_OV0_V_INC					0x0424
+#define R128_OV0_P1_V_ACCUM_INIT		0x0428
+#define R128_OV0_P23_V_ACCUM_INIT		0x042C
+#define R128_OV0_P1_BLANK_LINES_AT_TOP	0x0430
+#define R128_OV0_VID_BUF0_BASE_ADRS 	0x0440
+#define R128_OV0_VID_BUF_PITCH0_VALUE	0x0460
+#define R128_OV0_AUTO_FLIP_CNTL 		0x0470
+#define R128_OV0_H_INC					0x0480
+#define R128_OV0_STEP_BY				0x0484
+#define R128_OV0_P1_H_ACCUM_INIT		0x0488
+#define R128_OV0_P23_H_ACCUM_INIT		0x048C
+#define R128_OV0_P1_X_START_END 		0x0494
+#define R128_OV0_P2_X_START_END 		0x0498
+#define R128_OV0_P3_X_START_END 		0x049C
+#define R128_OV0_FILTER_CNTL			0x04A0
+#define R128_OV0_COLOUR_CNTL			0x04E0
+#define R128_OV0_GRAPHICS_KEY_CLR		0x04EC
+#define R128_OV0_GRAPHICS_KEY_MSK		0x04F0
+#define R128_OV0_KEY_CNTL				0x04F4
+#		define R128_GRAPHIC_KEY_FN_EQ	0x00000040L
+#		define R128_GRAPHIC_KEY_FN_NE	0x00000050L
+#define R128_OV0_TEST					0x04F8
+
+
+
 // Functions to get/set PLL registers.
 //=======================================
 
Index: src/add-ons/accelerants/ati/overlay.cpp
===================================================================
--- src/add-ons/accelerants/ati/overlay.cpp	(revision 0)
+++ src/add-ons/accelerants/ati/overlay.cpp	(revision 0)
@@ -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;
+}
Index: src/add-ons/accelerants/ati/mach64_overlay.cpp
===================================================================
--- src/add-ons/accelerants/ati/mach64_overlay.cpp	(revision 0)
+++ src/add-ons/accelerants/ati/mach64_overlay.cpp	(revision 0)
@@ -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
+}
Index: src/add-ons/accelerants/ati/hooks.cpp
===================================================================
--- src/add-ons/accelerants/ati/hooks.cpp	(revision 42305)
+++ src/add-ons/accelerants/ati/hooks.cpp	(working copy)
@@ -1,9 +1,9 @@
 /*
-	Copyright 2008 Haiku, Inc.  All rights reserved.
+	Copyright 2008, 2011 Haiku, Inc.  All rights reserved.
 	Distributed under the terms of the MIT license.
 
 	Authors:
-	Gerald Zajac 2008
+	Gerald Zajac
 */
 
 #include "accelerant.h"
@@ -16,51 +16,106 @@
 
 	switch (feature) {
 		// General
-		case B_INIT_ACCELERANT:				return (void*)InitAccelerant;
-		case B_UNINIT_ACCELERANT:			return (void*)UninitAccelerant;
-		case B_CLONE_ACCELERANT:			return (void*)CloneAccelerant;
-		case B_ACCELERANT_CLONE_INFO_SIZE:	return (void*)AccelerantCloneInfoSize;
-		case B_GET_ACCELERANT_CLONE_INFO:	return (void*)GetAccelerantCloneInfo;
-		case B_GET_ACCELERANT_DEVICE_INFO:	return (void*)GetAccelerantDeviceInfo;
-		case B_ACCELERANT_RETRACE_SEMAPHORE: return (void*)AccelerantRetraceSemaphore;
+		case B_INIT_ACCELERANT:
+			return (void*)InitAccelerant;
+		case B_UNINIT_ACCELERANT:
+			return (void*)UninitAccelerant;
+		case B_CLONE_ACCELERANT:
+			return (void*)CloneAccelerant;
+		case B_ACCELERANT_CLONE_INFO_SIZE:
+			return (void*)AccelerantCloneInfoSize;
+		case B_GET_ACCELERANT_CLONE_INFO:
+			return (void*)GetAccelerantCloneInfo;
+		case B_GET_ACCELERANT_DEVICE_INFO:
+			return (void*)GetAccelerantDeviceInfo;
+		case B_ACCELERANT_RETRACE_SEMAPHORE:
+			return (void*)AccelerantRetraceSemaphore;
 
 		// Mode Configuration
-		case B_ACCELERANT_MODE_COUNT:	return (void*)AccelerantModeCount;
-		case B_GET_MODE_LIST:			return (void*)GetModeList;
-		case B_PROPOSE_DISPLAY_MODE:	return (void*)ProposeDisplayMode;
-		case B_SET_DISPLAY_MODE:		return (void*)SetDisplayMode;
-		case B_GET_DISPLAY_MODE:		return (void*)GetDisplayMode;
-		case B_GET_PREFERRED_DISPLAY_MODE: return (void*)GetPreferredDisplayMode;
-		case B_GET_EDID_INFO:			return (void*)GetEdidInfo;
-		case B_GET_FRAME_BUFFER_CONFIG:	return (void*)GetFrameBufferConfig;
-		case B_GET_PIXEL_CLOCK_LIMITS:	return (void*)GetPixelClockLimits;
-		case B_MOVE_DISPLAY:			return (void*)MoveDisplay;
-		case B_SET_INDEXED_COLORS:		return (void*)(gInfo.SetIndexedColors);
-		case B_GET_TIMING_CONSTRAINTS:	return (void*)GetTimingConstraints;
+		case B_ACCELERANT_MODE_COUNT:
+			return (void*)AccelerantModeCount;
+		case B_GET_MODE_LIST:
+			return (void*)GetModeList;
+		case B_PROPOSE_DISPLAY_MODE:
+			return (void*)ProposeDisplayMode;
+		case B_SET_DISPLAY_MODE:
+			return (void*)SetDisplayMode;
+		case B_GET_DISPLAY_MODE:
+			return (void*)GetDisplayMode;
+		case B_GET_PREFERRED_DISPLAY_MODE:
+			return (void*)GetPreferredDisplayMode;
+		case B_GET_EDID_INFO:
+			return (void*)GetEdidInfo;
+		case B_GET_FRAME_BUFFER_CONFIG:
+			return (void*)GetFrameBufferConfig;
+		case B_GET_PIXEL_CLOCK_LIMITS:
+			return (void*)GetPixelClockLimits;
+		case B_MOVE_DISPLAY:
+			return (void*)MoveDisplay;
+		case B_SET_INDEXED_COLORS:
+			return (void*)(gInfo.SetIndexedColors);
+		case B_GET_TIMING_CONSTRAINTS:
+			return (void*)GetTimingConstraints;
 
 		// DPMS
-		case B_DPMS_CAPABILITIES:		return (void*)(gInfo.DPMSCapabilities);
-		case B_DPMS_MODE:				return (void*)(gInfo.GetDPMSMode);
-		case B_SET_DPMS_MODE:			return (void*)(gInfo.SetDPMSMode);
+		case B_DPMS_CAPABILITIES:
+			return (void*)(gInfo.DPMSCapabilities);
+		case B_DPMS_MODE:
+			return (void*)(gInfo.GetDPMSMode);
+		case B_SET_DPMS_MODE:
+			return (void*)(gInfo.SetDPMSMode);
 
 		// Cursor
-		case B_SET_CURSOR_SHAPE:		return (void*)SetCursorShape;
-		case B_MOVE_CURSOR:				return (void*)MoveCursor;
-		case B_SHOW_CURSOR:				return (void*)(gInfo.ShowCursor);
+		case B_SET_CURSOR_SHAPE:
+			return (void*)SetCursorShape;
+		case B_MOVE_CURSOR:
+			return (void*)MoveCursor;
+		case B_SHOW_CURSOR:
+			return (void*)(gInfo.ShowCursor);
 
 		// Engine Management
-		case B_ACCELERANT_ENGINE_COUNT:	return (void*)AccelerantEngineCount;
-		case B_ACQUIRE_ENGINE:			return (void*)AcquireEngine;
-		case B_RELEASE_ENGINE:			return (void*)ReleaseEngine;
-		case B_WAIT_ENGINE_IDLE:		return (void*)WaitEngineIdle;
-		case B_GET_SYNC_TOKEN:			return (void*)GetSyncToken;
-		case B_SYNC_TO_TOKEN:			return (void*)SyncToToken;
+		case B_ACCELERANT_ENGINE_COUNT:
+			return (void*)AccelerantEngineCount;
+		case B_ACQUIRE_ENGINE:
+			return (void*)AcquireEngine;
+		case B_RELEASE_ENGINE:
+			return (void*)ReleaseEngine;
+		case B_WAIT_ENGINE_IDLE:
+			return (void*)WaitEngineIdle;
+		case B_GET_SYNC_TOKEN:
+			return (void*)GetSyncToken;
+		case B_SYNC_TO_TOKEN:
+			return (void*)SyncToToken;
 
 		// 2D acceleration
-		case B_SCREEN_TO_SCREEN_BLIT:	return (void*)(gInfo.ScreenToScreenBlit);
-		case B_FILL_RECTANGLE:			return (void*)(gInfo.FillRectangle);
-		case B_INVERT_RECTANGLE:		return (void*)(gInfo.InvertRectangle);
-		case B_FILL_SPAN:				return (void*)(gInfo.FillSpan);
+		case B_SCREEN_TO_SCREEN_BLIT:
+			return (void*)(gInfo.ScreenToScreenBlit);
+		case B_FILL_RECTANGLE:
+			return (void*)(gInfo.FillRectangle);
+		case B_INVERT_RECTANGLE:
+			return (void*)(gInfo.InvertRectangle);
+		case B_FILL_SPAN:
+			return (void*)(gInfo.FillSpan);
+
+		// Overlay
+		case B_OVERLAY_COUNT:
+			return (void*)OverlayCount;
+		case B_OVERLAY_SUPPORTED_SPACES:
+			return (void*)OverlaySupportedSpaces;
+		case B_OVERLAY_SUPPORTED_FEATURES:
+			return (void*)OverlaySupportedFeatures;
+		case B_ALLOCATE_OVERLAY_BUFFER:
+			return (void*)AllocateOverlayBuffer;
+		case B_RELEASE_OVERLAY_BUFFER:
+			return (void*)ReleaseOverlayBuffer;
+		case B_GET_OVERLAY_CONSTRAINTS:
+			return (void*)GetOverlayConstraints;
+		case B_ALLOCATE_OVERLAY:
+			return (void*)AllocateOverlay;
+		case B_RELEASE_OVERLAY:
+			return (void*)ReleaseOverlay;
+		case B_CONFIGURE_OVERLAY:
+			return (void*)ConfigureOverlay;
 	}
 
 	return NULL;	// Return null pointer for any feature not handled above
Index: src/add-ons/accelerants/ati/Jamfile
===================================================================
--- src/add-ons/accelerants/ati/Jamfile	(revision 42305)
+++ src/add-ons/accelerants/ati/Jamfile	(working copy)
@@ -10,12 +10,14 @@
 	engine.cpp
 	hooks.cpp
 	mode.cpp
+	overlay.cpp
 		
 	mach64_cursor.cpp
 	mach64_dpms.cpp
 	mach64_draw.cpp
 	mach64_init.cpp
 	mach64_mode.cpp
+	mach64_overlay.cpp
 	mach64_util.cpp
 	
 	rage128_cursor.cpp
@@ -23,6 +25,7 @@
 	rage128_draw.cpp
 	rage128_init.cpp
 	rage128_mode.cpp
+	rage128_overlay.cpp
 
 	: be libaccelerantscommon.a
 ;
Index: src/add-ons/accelerants/ati/mach64.h
===================================================================
--- src/add-ons/accelerants/ati/mach64.h	(revision 42305)
+++ src/add-ons/accelerants/ati/mach64.h	(working copy)
@@ -1,13 +1,14 @@
 /*
-	Haiku ATI video driver adapted from the X.org ATI driver.
+	Haiku ATI video driver adapted from the X.org ATI driver which has the
+	following copyright:
 
 	Copyright 1992,1993,1994,1995,1996,1997 by Kevin E. Martin, Chapel Hill, North Carolina.
 
-	Copyright 2009 Haiku, Inc.  All rights reserved.
+	Copyright 2009, 2011 Haiku, Inc.  All rights reserved.
 	Distributed under the terms of the MIT license.
 
 	Authors:
-	Gerald Zajac 2009
+	Gerald Zajac
 */
 
 #ifndef __MACH64_H__
@@ -178,6 +179,39 @@
 #define GUI_STAT				(0x0c00 + 0x0338)	// Dword offset CE
 
 
+// Definitions used for overlays.
+//===============================
+
+#define REG_BLOCK_1	0x0800		// offset of register block 1 in register area
+
+#define OVERLAY_Y_X_START		(REG_BLOCK_1 + 0x0000)	// Dword offset 00
+#define OVERLAY_LOCK_START		0x80000000ul
+#define OVERLAY_Y_X_END			(REG_BLOCK_1 + 0x0004)	// Dword offset 01
+#define OVERLAY_GRAPHICS_KEY_CLR (REG_BLOCK_1 + 0x0010)	// Dword offset 04
+#define OVERLAY_GRAPHICS_KEY_MSK (REG_BLOCK_1 + 0x0014)	// Dword offset 05
+#define OVERLAY_KEY_CNTL		(REG_BLOCK_1 + 0x0018)	// Dword offset 06
+#define OVERLAY_MIX_FALSE		0x00
+#define OVERLAY_MIX_EQUAL		0x50
+#define OVERLAY_SCALE_INC		(REG_BLOCK_1 + 0x0020)	// Dword offset 08
+#define OVERLAY_SCALE_CNTL		(REG_BLOCK_1 + 0x0024)	// Dword offset 09
+#define SCALE_PIX_EXPAND		0x00000001
+#define OVERLAY_EN				0x40000000
+#define SCALE_EN				0x80000000
+#define SCALER_HEIGHT_WIDTH		(REG_BLOCK_1 + 0x0028)	// Dword offset 0a
+#define SCALER_BUF0_OFFSET		(REG_BLOCK_1 + 0x0034)	// Dword offset 0d
+#define SCALER_BUF0_PITCH		(REG_BLOCK_1 + 0x003c)	// Dword offset 0f
+#define VIDEO_FORMAT			(REG_BLOCK_1 + 0x0048)	// Dword offset 12
+#define SCALE_IN_VYUY422		0x000b0000
+#define BUF0_OFFSET				(REG_BLOCK_1 + 0x0080)	// Dword offset 20
+#define BUF0_PITCH				(REG_BLOCK_1 + 0x008c)	// Dword offset 23
+#define SCALER_COLOUR_CNTL		(REG_BLOCK_1 + 0x0150)	// Dword offset 54
+#define SCALER_H_COEFF0			(REG_BLOCK_1 + 0x0154)	// Dword offset 55
+#define SCALER_H_COEFF1			(REG_BLOCK_1 + 0x0158)	// Dword offset 56
+#define SCALER_H_COEFF2			(REG_BLOCK_1 + 0x015c)	// Dword offset 57
+#define SCALER_H_COEFF3			(REG_BLOCK_1 + 0x0160)	// Dword offset 58
+#define SCALER_H_COEFF4			(REG_BLOCK_1 + 0x0164)	// Dword offset 59
+
+
 // CRTC control values.
 
 #define CRTC_H_SYNC_NEG			0x00200000
@@ -225,11 +259,10 @@
 #define CRTC_PITCH				0xffc00000
 
 // DAC control values.
-
 #define DAC_8BIT_EN				0x00000100
 
+
 // Mix control values.
-
 #define MIX_NOT_DST				0x0000
 #define MIX_0 					0x0001
 #define MIX_1 					0x0002
@@ -250,7 +283,7 @@
 // BUS_CNTL register constants.
 #define BUS_FIFO_ERR_ACK		0x00200000
 #define BUS_HOST_ERR_ACK		0x00800000
-#define BUS_APER_REG_DIS		0x00000010
+#define BUS_EXT_REG_EN			0x08000000
 
 // GEN_TEST_CNTL register constants.
 #define GEN_OVR_OUTPUT_EN		0x20
@@ -361,13 +394,13 @@
 #define BYTE_ORDER_LSB_TO_MSB 0x1000000
 
 // DP_SRC register constants.
-#define BKGD_SRC_BKGD_CLR 		0
-#define FRGD_SRC_FRGD_CLR 		0x100
-#define FRGD_SRC_BLIT 			0x300
-#define MONO_SRC_ONE				0
+#define BKGD_SRC_BKGD_CLR 	0
+#define FRGD_SRC_FRGD_CLR 	0x100
+#define FRGD_SRC_BLIT 		0x300
+#define MONO_SRC_ONE		0
 
 // GUI_STAT register constants.
-#define ENGINE_BUSY 				1
+#define ENGINE_BUSY 		1
 
 // LCD Index register constants.
 #define LCD_REG_INDEX		0x0000003F
