xref: /haiku/src/add-ons/accelerants/ati/rage128_overlay.cpp (revision 830f67ef991407f287dbc1238aa5f5906d90c991)
1 /*
2 	Haiku ATI video driver adapted from the X.org ATI driver which has the
3 	following copyright:
4 
5 	Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
6 						 Precision Insight, Inc., Cedar Park, Texas, and
7 						 VA Linux Systems Inc., Fremont, California.
8 
9 	Copyright 2011 Haiku, Inc.  All rights reserved.
10 	Distributed under the terms of the MIT license.
11 
12 	Authors:
13 	Gerald Zajac
14  */
15 
16 #include "accelerant.h"
17 #include "rage128.h"
18 
19 
20 static uint32 sCurrentKeyColor = 0;
21 static uint32 sCurrentKeyMask = 0;
22 
23 
24 
25 bool
26 Rage128_DisplayOverlay(const overlay_window* window,
27 						const overlay_buffer* buffer)
28 {
29 	// Return true if setup is successful.
30 
31 	SharedInfo& si = *gInfo.sharedInfo;
32 
33 	if (window == NULL || buffer == NULL)
34 		return false;
35 
36 	if (buffer->space != B_YCbCr422)
37 		return false;	// color space not supported
38 
39 	uint32 keyColor = 0;
40 	uint32 keyMask = 0;
41 
42 	switch (si.displayMode.bitsPerPixel) {
43 		case 15:
44 			keyMask = 0x7fff;
45 			keyColor = (window->blue.value & window->blue.mask) << 0
46 				| (window->green.value & window->green.mask) << 5
47 				| (window->red.value & window->red.mask) << 10;
48 				// 15 bit color has no alpha bits
49 			break;
50 		case 16:
51 			keyMask = 0xffff;
52 			keyColor = (window->blue.value & window->blue.mask) << 0
53 				| (window->green.value & window->green.mask) << 5
54 				| (window->red.value & window->red.mask) << 11;
55 				// 16 bit color has no alpha bits
56 			break;
57 		default:
58 			keyMask = 0xffffffff;
59 			keyColor = (window->blue.value & window->blue.mask) << 0
60 				| (window->green.value & window->green.mask) << 8
61 				| (window->red.value & window->red.mask) << 16
62 				| (window->alpha.value & window->alpha.mask) << 24;
63 			break;
64 	}
65 
66 	// If the key color or key mask has changed since the overlay was
67 	// previously initialized, initialize it again.  This is to avoid
68 	// initializing the overlay video everytime the overlay buffer is
69 	// switched which causes artifacts in the overlay display.
70 
71 	if (keyColor != sCurrentKeyColor || keyMask != sCurrentKeyMask)
72 	{
73 		TRACE("Rage128_DisplayOverlay() initializing overlay video\n");
74 
75 		// Initialize the overlay video by first resetting the video.
76 
77 		OUTREG(R128_OV0_SCALE_CNTL, 0);
78 		OUTREG(R128_OV0_EXCLUSIVE_HORZ, 0);
79 		OUTREG(R128_OV0_AUTO_FLIP_CNTL, 0);
80 		OUTREG(R128_OV0_FILTER_CNTL, 0x0000000f);
81 
82 		const uint32 brightness = 0;
83 		const uint32 saturation = 16;
84 		OUTREG(R128_OV0_COLOUR_CNTL, brightness | saturation << 8
85 			| saturation << 16);
86 
87 		OUTREG(R128_OV0_GRAPHICS_KEY_MSK, keyMask);
88 		OUTREG(R128_OV0_GRAPHICS_KEY_CLR, keyColor);
89 		OUTREG(R128_OV0_KEY_CNTL, R128_GRAPHIC_KEY_FN_NE);
90 		OUTREG(R128_OV0_TEST, 0);
91 
92 		sCurrentKeyColor = keyColor;
93 		sCurrentKeyMask = keyMask;
94 	}
95 
96 	uint32 ecpDiv;
97 	if (si.displayMode.timing.pixel_clock < 125000)
98 		ecpDiv = 0;
99 	else if (si.displayMode.timing.pixel_clock < 250000)
100 		ecpDiv = 1;
101 	else
102 		ecpDiv = 2;
103 
104 	SetPLLReg(R128_VCLK_ECP_CNTL, ecpDiv << 8, R128_ECP_DIV_MASK);
105 
106 	int32 vertInc = (buffer->height << 20) / window->height;
107 	int32 horzInc = (buffer->width << (12 + ecpDiv)) / window->width;
108 	int32 stepBy = 1;
109 
110 	while (horzInc >= (2 << 12)) {
111 		stepBy++;
112 		horzInc >>= 1;
113 	}
114 
115 	int32 x1 = window->h_start;
116 	int32 y1 = window->v_start;
117 
118 	int32 x2 = window->h_start + window->width;
119 	int32 y2 = window->v_start + window->height;
120 
121 	int32 left = x1;
122 	int32 tmp = (left & 0x0003ffff) + 0x00028000 + (horzInc << 3);
123 	int32 p1_h_accum_init = ((tmp << 4) & 0x000f8000) |
124 					  ((tmp << 12) & 0xf0000000);
125 
126 	tmp = ((left >> 1) & 0x0001ffff) + 0x00028000 + (horzInc << 2);
127 	int32 p23_h_accum_init = ((tmp << 4) & 0x000f8000) |
128 						((tmp << 12) & 0x70000000);
129 
130 	tmp = (y1 & 0x0000ffff) + 0x00018000;
131 	int32 p1_v_accum_init = ((tmp << 4) & 0x03ff8000) | 0x00000001;
132 
133 	// Compute offset of overlay buffer in the video memory.
134 	uint32 offset = (uint32)((addr_t)buffer->buffer - si.videoMemAddr);
135 
136 	OUTREG(R128_OV0_REG_LOAD_CNTL, 1);
137 	while (!(INREG(R128_OV0_REG_LOAD_CNTL) & (1 << 3)))
138 		;
139 
140 	OUTREG(R128_OV0_H_INC, horzInc | ((horzInc >> 1) << 16));
141 	OUTREG(R128_OV0_STEP_BY, stepBy | (stepBy << 8));
142 	OUTREG(R128_OV0_Y_X_START, x1 | y1 << 16);
143 	OUTREG(R128_OV0_Y_X_END, x2 | y2 << 16);
144 	OUTREG(R128_OV0_V_INC, vertInc);
145 	OUTREG(R128_OV0_P1_BLANK_LINES_AT_TOP,
146 			0x00000fff | ((buffer->height - 1) << 16));
147 	OUTREG(R128_OV0_VID_BUF_PITCH0_VALUE, buffer->bytes_per_row);
148 
149 	int32 width = window->width;
150 	left = 0;
151 	OUTREG(R128_OV0_P1_X_START_END, (width - 1) | (left << 16));
152 	width >>= 1;
153 	OUTREG(R128_OV0_P2_X_START_END, (width - 1) | (left << 16));
154 	OUTREG(R128_OV0_P3_X_START_END, (width - 1) | (left << 16));
155 	OUTREG(R128_OV0_VID_BUF0_BASE_ADRS, offset);
156 	OUTREG(R128_OV0_P1_V_ACCUM_INIT, p1_v_accum_init);
157 	OUTREG(R128_OV0_P23_V_ACCUM_INIT, 0);
158 	OUTREG(R128_OV0_P1_H_ACCUM_INIT, p1_h_accum_init);
159 	OUTREG(R128_OV0_P23_H_ACCUM_INIT, p23_h_accum_init);
160 
161 	OUTREG(R128_OV0_SCALE_CNTL, 0x41FF8B03);
162 	OUTREG(R128_OV0_REG_LOAD_CNTL, 0);
163 
164 	return true;
165 }
166 
167 
168 void
169 Rage128_StopOverlay(void)
170 {
171 	OUTREG(R128_OV0_SCALE_CNTL, 0);		// reset the video
172 
173 	// Reset the key color and mask so that when the overlay is started again
174 	// it will be initialized.
175 
176 	sCurrentKeyColor = 0;
177 	sCurrentKeyMask = 0;
178 }
179