xref: /haiku/src/add-ons/accelerants/ati/mach64_overlay.cpp (revision 83b1a68c52ba3e0e8796282759f694b7fdddf06d)
1 /*
2 	Haiku ATI video driver adapted from the X.org ATI driver which has the
3 	following copyright:
4 
5 	Copyright 2003 through 2004 by Marc Aurele La France, tsi@xfree86.org
6 
7 	Copyright 2011 Haiku, Inc.  All rights reserved.
8 	Distributed under the terms of the MIT license.
9 
10 	Authors:
11 	Gerald Zajac
12 */
13 
14 #include "accelerant.h"
15 #include "mach64.h"
16 
17 
18 
19 bool
20 Mach64_DisplayOverlay(const overlay_window* window,
21 						const overlay_buffer* buffer)
22 {
23 	// Return true if setup is successful.
24 
25 	SharedInfo& si = *gInfo.sharedInfo;
26 
27 	if (window == NULL || buffer == NULL)
28 		return false;
29 
30 	uint32 videoFormat;
31 
32 	if (buffer->space == B_YCbCr422)
33 		videoFormat = SCALE_IN_VYUY422;
34 	else
35 		return false;	// color space not supported
36 
37 	int32 x1 = (window->h_start < 0) ? 0 : window->h_start;
38 	int32 y1 = (window->v_start < 0) ? 0 : window->v_start;
39 
40 	int32 x2 = window->h_start + window->width - 1;
41 	int32 y2 = window->v_start + window->height - 1;
42 
43 	if (x2 > si.displayMode.timing.h_display)
44 		x2 = si.displayMode.timing.h_display;
45 
46 	if (y2 > si.displayMode.timing.v_display)
47 		y2 = si.displayMode.timing.v_display;
48 
49 	// If window is moved beyond edge of screen, do not allow width < 4 or
50 	// height < 4;  otherwise there is a possibilty of divide by zero when
51 	// computing the scale factors..
52 	if (x2 < x1 + 4)
53 		x2 = x1 + 4;
54 
55 	if (y2 < y1 + 4)
56 		y2 = y1 + 4;
57 
58 	// Calculate overlay scale factors.
59 	uint32 horzScale = (buffer->width << 12) / (x2 - x1 + 1);
60 	uint32 vertScale = (buffer->height << 12) / (y2 - y1 + 1);
61 
62 	if (horzScale > 0xffff)		// only 16 bits are used for scale factors
63 		horzScale = 0xffff;
64 	if (vertScale > 0xffff)
65 		vertScale = 0xffff;
66 
67 	gInfo.WaitForFifo(2);
68 	OUTREG(BUS_CNTL, INREG(BUS_CNTL) | BUS_EXT_REG_EN);	// enable reg block 1
69 	OUTREG(OVERLAY_SCALE_CNTL, SCALE_EN);	// reset the video
70 
71 	if (si.chipType >= MACH64_264GTPRO) {
72 		const uint32 brightness = 0;
73 		const uint32 saturation = 12;
74 
75 		gInfo.WaitForFifo(6);
76 		OUTREG(SCALER_COLOUR_CNTL, brightness | saturation << 8
77 			| saturation << 16);
78 		OUTREG(SCALER_H_COEFF0, 0x0002000);
79 		OUTREG(SCALER_H_COEFF1, 0xd06200d);
80 		OUTREG(SCALER_H_COEFF2, 0xd0a1c0d);
81 		OUTREG(SCALER_H_COEFF3, 0xc0e1a0c);
82 		OUTREG(SCALER_H_COEFF4, 0xc14140c);
83 	}
84 
85 	uint32 keyColor = 0;
86 	uint32 keyMask = 0;
87 
88 	switch (si.displayMode.bitsPerPixel) {
89 		case 15:
90 			keyMask = 0x7fff;
91 			keyColor = (window->blue.value & window->blue.mask) << 0
92 				| (window->green.value & window->green.mask) << 5
93 				| (window->red.value & window->red.mask) << 10;
94 				// 15 bit color has no alpha bits
95 			break;
96 		case 16:
97 			keyMask = 0xffff;
98 			keyColor = (window->blue.value & window->blue.mask) << 0
99 				| (window->green.value & window->green.mask) << 5
100 				| (window->red.value & window->red.mask) << 11;
101 				// 16 bit color has no alpha bits
102 			break;
103 		default:
104 			keyMask = 0xffffffff;
105 			keyColor = (window->blue.value & window->blue.mask) << 0
106 				| (window->green.value & window->green.mask) << 8
107 				| (window->red.value & window->red.mask) << 16
108 				| (window->alpha.value & window->alpha.mask) << 24;
109 			break;
110 	}
111 
112 	gInfo.WaitForFifo(3);
113 	OUTREG(OVERLAY_GRAPHICS_KEY_MSK, keyMask);
114 	OUTREG(OVERLAY_GRAPHICS_KEY_CLR, keyColor);
115 	OUTREG(OVERLAY_KEY_CNTL, OVERLAY_MIX_FALSE | OVERLAY_MIX_EQUAL);
116 
117 	gInfo.WaitForFifo(8);
118 	OUTREG(OVERLAY_Y_X_START, OVERLAY_LOCK_START | (x1 << 16) | y1);
119 	OUTREG(OVERLAY_Y_X_END, (x2 << 16) | y2);
120 	OUTREG(OVERLAY_SCALE_INC, (horzScale << 16) | vertScale);
121 	OUTREG(SCALER_HEIGHT_WIDTH, (buffer->width << 16) | buffer->height);
122 	OUTREG(VIDEO_FORMAT, videoFormat);
123 
124 	// Compute offset of overlay buffer in the video memory.
125 	uint32 offset = uint32(buffer->buffer) - si.videoMemAddr;
126 
127 	if (si.chipType < MACH64_264VTB) {
128 		OUTREG(BUF0_OFFSET, offset);
129 		OUTREG(BUF0_PITCH, buffer->width);
130 	} else {
131 		OUTREG(SCALER_BUF0_OFFSET, offset);
132 		OUTREG(SCALER_BUF0_PITCH, buffer->width);
133 	}
134 
135 	OUTREG(OVERLAY_SCALE_CNTL, SCALE_PIX_EXPAND | OVERLAY_EN | SCALE_EN);
136 
137 	return true;
138 }
139 
140 
141 void
142 Mach64_StopOverlay(void)
143 {
144 	OUTREG(OVERLAY_SCALE_CNTL, SCALE_EN);	// reset the video
145 }
146