1/*
2 * Copyright 2010 Haiku, Inc.  All rights reserved.
3 * Distributed under the terms of the MIT license.
4 *
5 * Authors:
6 *		Gerald Zajac
7 */
8
9#include "accelerant.h"
10#include "3dfx.h"
11
12
13
14bool
15TDFX_DisplayOverlay(const overlay_window* window,
16						const overlay_buffer* buffer,
17						const overlay_view* view)
18{
19	// Return true if setup is successful.
20
21	SharedInfo& si = *gInfo.sharedInfo;
22
23	if (window == NULL || buffer == NULL || view == NULL)
24		return false;
25
26	if (window->flags & B_OVERLAY_COLOR_KEY) {
27		uint32 color = 0;
28
29		if (si.displayMode.bitsPerPixel == 16) {
30			color = (window->blue.value & window->blue.mask) << 0
31				  | (window->green.value & window->green.mask) << 5
32				  | (window->red.value & window->red.mask) << 11;
33				  // 16 bit color has no alpha bits
34		} else {
35			color = (window->blue.value & window->blue.mask) << 0
36				  | (window->green.value & window->green.mask) << 8
37				  | (window->red.value & window->red.mask) << 16
38				  | (window->alpha.value & window->alpha.mask) << 24;
39		}
40
41		TDFX_WaitForFifo(2);
42		OUTREG32(VIDEO_CHROMA_MIN, color);
43		OUTREG32(VIDEO_CHROMA_MAX, color);
44	}
45
46	uint32 videoConfig = INREG32(VIDEO_PROC_CONFIG);
47	videoConfig &= ~VIDEO_PROC_CONFIG_MASK;
48	videoConfig |= (0x00000320 | OVERLAY_CLUT_BYPASS);
49
50	// Scale image if window dimension is larger than the buffer dimension.
51	// Scaling is not done if window dimension is smaller since the chip only
52	// scales up to a larger dimension, and does not scale down to a smaller
53	// dimension.
54
55	if (window->width > buffer->width)
56		videoConfig |= (1 << 14);
57	if (window->height > buffer->height)
58		videoConfig |= (1 << 15);
59
60	switch (buffer->space) {
61		case B_YCbCr422:
62			videoConfig |= VIDCFG_OVL_FMT_YUYV422;
63			break;
64		case B_RGB16:
65			videoConfig |= VIDCFG_OVL_FMT_RGB565;
66			break;
67		default:
68			return false;	// color space not supported
69	}
70
71	// can't do bilinear filtering when in 2X mode
72	if ((videoConfig & VIDEO_2X_MODE_ENABLE) == 0)
73		videoConfig |= (3 << 16);
74
75	TDFX_WaitForFifo(1);
76	OUTREG32(VIDEO_PROC_CONFIG, videoConfig);
77
78	// Subtract 1 from height to eliminate junk on last line of image.
79	int32 dudx = (buffer->width << 20) / window->width;
80	int32 dudy = ((buffer->height - 1) << 20) / window->height;
81
82	int32 x1 = (window->h_start < 0) ? 0 : window->h_start;
83	int32 y1 = (window->v_start < 0) ? 0 : window->v_start;
84
85	int32 x2 = x1 + window->width - 1;
86	int32 y2 = y1 + window->height - 1;
87
88	TDFX_WaitForFifo(6);
89
90	// Set up coordinates of overlay window on screen.
91	OUTREG32(VIDEO_OVERLAY_START_COORDS, x1 | (y1 << 12));
92	OUTREG32(VIDEO_OVERLAY_END_COORDS, x2 | (y2 << 12));
93	// Set up scale and position of overlay in graphics memory.
94	OUTREG32(VIDEO_OVERLAY_DUDX, dudx);
95	OUTREG32(VIDEO_OVERLAY_DUDX_OFFSET_SRC_WIDTH, ((x1 & 0x0001ffff) << 3)
96		| (buffer->width << 20));
97	OUTREG32(VIDEO_OVERLAY_DVDY, dudy);
98	OUTREG32(VIDEO_OVERLAY_DVDY_OFFSET, (y1 & 0x0000ffff) << 3);
99
100	// Add width of overlay buffer to stride.
101	uint32 stride = INREG32(VIDEO_DESKTOP_OVERLAY_STRIDE) & 0x0000ffff;
102	stride |= (buffer->width << 1) << 16;
103	uint32 offset = (uint32)(addr_t)buffer->buffer_dma;
104
105	TDFX_WaitForFifo(2);
106
107	OUTREG32(VIDEO_DESKTOP_OVERLAY_STRIDE, stride);
108	OUTREG32(VIDEO_IN_ADDR0, offset);
109
110	return true;
111}
112
113
114void
115TDFX_StopOverlay(void)
116{
117	// reset the video
118	uint32 videoConfig = INREG32(VIDEO_PROC_CONFIG) & ~VIDEO_PROC_CONFIG_MASK;
119	OUTREG32(VIDEO_PROC_CONFIG, videoConfig);
120	OUTREG32(RGB_MAX_DELTA, 0x0080808);
121}
122