xref: /haiku/src/servers/app/DirectWindowInfo.cpp (revision 7d6915b4d08ffe728cd38af02843d5e98ddfe0db)
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 
23 DirectWindowInfo::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);
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 
44 DirectWindowInfo::~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 
56 status_t
57 DirectWindowInfo::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 
70 status_t
71 DirectWindowInfo::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 
81 status_t
82 DirectWindowInfo::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 (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_RGB32:
102 			case B_RGBA32:
103 			case B_RGB32_BIG:
104 			case B_RGBA32_BIG:
105 				fBufferInfo->bits_per_pixel = 32;
106 				break;
107 			case B_RGB24:
108 			case B_RGB24_BIG:
109 				fBufferInfo->bits_per_pixel = 24;
110 				break;
111 			case B_RGB16:
112 			case B_RGB16_BIG:
113 			case B_RGB15:
114 			case B_RGB15_BIG:
115 				fBufferInfo->bits_per_pixel = 16;
116 				break;
117 			case B_CMAP8:
118 			case B_GRAY8:
119 				fBufferInfo->bits_per_pixel = 8;
120 				break;
121 			default:
122 				syslog(LOG_ERR,
123 					"unknown colorspace in DirectWindowInfo::SetState()!\n");
124 				fBufferInfo->bits_per_pixel = 0;
125 				break;
126 		}
127 
128 		fBufferInfo->pixel_format = buffer->ColorSpace();
129 		fBufferInfo->layout = B_BUFFER_NONINTERLEAVED;
130 		fBufferInfo->orientation = B_BUFFER_TOP_TO_BOTTOM;
131 			// TODO
132 		fBufferInfo->window_bounds = to_clipping_rect(windowFrame);
133 
134 		const int32 kMaxClipRectsCount = (DIRECT_BUFFER_INFO_AREA_SIZE
135 			- sizeof(direct_buffer_info)) / sizeof(clipping_rect);
136 
137 		fBufferInfo->clip_list_count = min_c(clipRegion.CountRects(),
138 			kMaxClipRectsCount);
139 		fBufferInfo->clip_bounds = clipRegion.FrameInt();
140 
141 		for (uint32 i = 0; i < fBufferInfo->clip_list_count; i++)
142 			fBufferInfo->clip_list[i] = clipRegion.RectAtInt(i);
143 	}
144 
145 	return _SyncronizeWithClient();
146 }
147 
148 
149 void
150 DirectWindowInfo::EnableFullScreen(const BRect& frame, window_feel feel)
151 {
152 	fOriginalFrame = frame;
153 	fOriginalFeel = feel;
154 	fFullScreen = true;
155 }
156 
157 
158 void
159 DirectWindowInfo::DisableFullScreen()
160 {
161 	fFullScreen = false;
162 }
163 
164 
165 status_t
166 DirectWindowInfo::_SyncronizeWithClient()
167 {
168 	// Releasing this semaphore causes the client to call
169 	// BDirectWindow::DirectConnected()
170 	status_t status = release_sem(fSem);
171 	if (status != B_OK)
172 		return status;
173 
174 	// Wait with a timeout of half a second until the client exits
175 	// from its DirectConnected() implementation
176 	do {
177 		status = acquire_sem_etc(fAcknowledgeSem, 1, B_TIMEOUT, 500000);
178 	} while (status == B_INTERRUPTED);
179 
180 	return status;
181 }
182