1/*
2 * Copyright 2008-2009, Haiku.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Stefano Ceccherini <stefano.ceccherini@gmail.com>
7 *		Axel D��rfler, axeld@pinc-software.de
8 */
9
10
11#include "DirectWindowInfo.h"
12
13#include <stdio.h>
14#include <string.h>
15#include <syslog.h>
16
17#include <Autolock.h>
18
19#include "RenderingBuffer.h"
20#include "clipping.h"
21
22
23DirectWindowInfo::DirectWindowInfo()
24	:
25	fBufferInfo(NULL),
26	fSem(-1),
27	fAcknowledgeSem(-1),
28	fBufferArea(-1),
29	fOriginalFeel(B_NORMAL_WINDOW_FEEL),
30	fFullScreen(false)
31{
32	fBufferArea = create_area("direct area", (void**)&fBufferInfo,
33		B_ANY_ADDRESS, DIRECT_BUFFER_INFO_AREA_SIZE,
34		B_NO_LOCK, B_READ_AREA | B_WRITE_AREA | B_CLONEABLE_AREA);
35
36	memset(fBufferInfo, 0, DIRECT_BUFFER_INFO_AREA_SIZE);
37	fBufferInfo->buffer_state = B_DIRECT_STOP;
38
39	fSem = create_sem(0, "direct sem");
40	fAcknowledgeSem = create_sem(0, "direct sem ack");
41}
42
43
44DirectWindowInfo::~DirectWindowInfo()
45{
46	// this should make the client die in case it's still running
47	fBufferInfo->bits = NULL;
48	fBufferInfo->bytes_per_row = 0;
49
50	delete_area(fBufferArea);
51	delete_sem(fSem);
52	delete_sem(fAcknowledgeSem);
53}
54
55
56status_t
57DirectWindowInfo::InitCheck() const
58{
59	if (fBufferArea < B_OK)
60		return fBufferArea;
61	if (fSem < B_OK)
62		return fSem;
63	if (fAcknowledgeSem < B_OK)
64		return fAcknowledgeSem;
65
66	return B_OK;
67}
68
69
70status_t
71DirectWindowInfo::GetSyncData(direct_window_sync_data& data) const
72{
73	data.area = fBufferArea;
74	data.disable_sem = fSem;
75	data.disable_sem_ack = fAcknowledgeSem;
76
77	return B_OK;
78}
79
80
81status_t
82DirectWindowInfo::SetState(direct_buffer_state bufferState,
83	direct_driver_state driverState, RenderingBuffer* buffer,
84	const BRect& windowFrame, const BRegion& clipRegion)
85{
86	if ((fBufferInfo->buffer_state & B_DIRECT_MODE_MASK) == B_DIRECT_STOP
87		&& (bufferState & B_DIRECT_MODE_MASK) != B_DIRECT_START)
88		return B_OK;
89
90	fBufferInfo->buffer_state = bufferState;
91
92	if ((int)driverState != -1)
93		fBufferInfo->driver_state = driverState;
94
95	if ((bufferState & B_DIRECT_MODE_MASK) != B_DIRECT_STOP) {
96		fBufferInfo->bits = buffer->Bits();
97		fBufferInfo->pci_bits = NULL; // TODO
98		fBufferInfo->bytes_per_row = buffer->BytesPerRow();
99
100		switch (buffer->ColorSpace()) {
101			case B_RGBA64:
102			case B_RGBA64_BIG:
103				fBufferInfo->bits_per_pixel = 64;
104				break;
105			case B_RGB48:
106			case B_RGB48_BIG:
107				fBufferInfo->bits_per_pixel = 48;
108				break;
109			case B_RGB32:
110			case B_RGBA32:
111			case B_RGB32_BIG:
112			case B_RGBA32_BIG:
113				fBufferInfo->bits_per_pixel = 32;
114				break;
115			case B_RGB24:
116			case B_RGB24_BIG:
117				fBufferInfo->bits_per_pixel = 24;
118				break;
119			case B_RGB16:
120			case B_RGB16_BIG:
121			case B_RGB15:
122			case B_RGB15_BIG:
123				fBufferInfo->bits_per_pixel = 16;
124				break;
125			case B_CMAP8:
126			case B_GRAY8:
127				fBufferInfo->bits_per_pixel = 8;
128				break;
129			default:
130				syslog(LOG_ERR,
131					"unknown colorspace in DirectWindowInfo::SetState()!\n");
132				fBufferInfo->bits_per_pixel = 0;
133				break;
134		}
135
136		fBufferInfo->pixel_format = buffer->ColorSpace();
137		fBufferInfo->layout = B_BUFFER_NONINTERLEAVED;
138		fBufferInfo->orientation = B_BUFFER_TOP_TO_BOTTOM;
139			// TODO
140		fBufferInfo->window_bounds = to_clipping_rect(windowFrame);
141
142		const int32 kMaxClipRectsCount = (DIRECT_BUFFER_INFO_AREA_SIZE
143			- sizeof(direct_buffer_info)) / sizeof(clipping_rect);
144
145		fBufferInfo->clip_list_count = min_c(clipRegion.CountRects(),
146			kMaxClipRectsCount);
147		fBufferInfo->clip_bounds = clipRegion.FrameInt();
148
149		for (uint32 i = 0; i < fBufferInfo->clip_list_count; i++)
150			fBufferInfo->clip_list[i] = clipRegion.RectAtInt(i);
151	}
152
153	return _SyncronizeWithClient();
154}
155
156
157void
158DirectWindowInfo::EnableFullScreen(const BRect& frame, window_feel feel)
159{
160	fOriginalFrame = frame;
161	fOriginalFeel = feel;
162	fFullScreen = true;
163}
164
165
166void
167DirectWindowInfo::DisableFullScreen()
168{
169	fFullScreen = false;
170}
171
172
173status_t
174DirectWindowInfo::_SyncronizeWithClient()
175{
176	// Releasing this semaphore causes the client to call
177	// BDirectWindow::DirectConnected()
178	status_t status = release_sem(fSem);
179	if (status != B_OK)
180		return status;
181
182	// Wait with a timeout of half a second until the client exits
183	// from its DirectConnected() implementation
184	do {
185		status = acquire_sem_etc(fAcknowledgeSem, 1, B_TIMEOUT, 500000);
186	} while (status == B_INTERRUPTED);
187
188	return status;
189}
190