xref: /haiku/src/kits/interface/PrivateScreen.cpp (revision 3a2b67b5ae3750e6a2963e575e7ee2b39f91bf6d)
1 /*
2  * Copyright 2002-2009, Haiku Inc.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Stefano Ceccherini (burton666@libero.it)
7  *		Axel Dörfler, axeld@pinc-software.de
8  */
9 
10 
11 /*!	BPrivateScreen is the class which does the real work for
12 	the proxy class BScreen (it interacts with the app_server).
13 */
14 
15 
16 #include <PrivateScreen.h>
17 
18 #include <new>
19 #include <pthread.h>
20 #include <stdlib.h>
21 
22 #include <Application.h>
23 #include <Autolock.h>
24 #include <Bitmap.h>
25 #include <Locker.h>
26 #include <ObjectList.h>
27 #include <Window.h>
28 
29 #include <AutoLocker.h>
30 
31 #include <AppMisc.h>
32 #include <AppServerLink.h>
33 #include <ServerProtocol.h>
34 
35 
36 using namespace BPrivate;
37 
38 
39 namespace {
40 
41 struct Screens {
42 	BObjectList<BPrivateScreen>	list;
43 
Screens__anon3c02a1cd0111::Screens44 	Screens()
45 		:
46 		list(2, true),
47 		fLock("screen list")
48 	{
49 	}
50 
Lock__anon3c02a1cd0111::Screens51 	bool Lock()
52 	{
53 		return fLock.Lock();
54 	}
55 
Unlock__anon3c02a1cd0111::Screens56 	void Unlock()
57 	{
58 		fLock.Unlock();
59 	}
60 
Default__anon3c02a1cd0111::Screens61 	static Screens* Default()
62 	{
63 		if (sDefaultInstance == NULL)
64 			pthread_once(&sDefaultInitOnce, &_InitSingleton);
65 
66 		return sDefaultInstance;
67 	}
68 
69 private:
_InitSingleton__anon3c02a1cd0111::Screens70 	static void _InitSingleton()
71 	{
72 		sDefaultInstance = new Screens;
73 	}
74 
75 private:
76 	BLocker					fLock;
77 
78 	static pthread_once_t	sDefaultInitOnce;
79 	static Screens*			sDefaultInstance;
80 };
81 
82 pthread_once_t Screens::sDefaultInitOnce = PTHREAD_ONCE_INIT;
83 Screens* Screens::sDefaultInstance = NULL;
84 
85 }	// unnamed namespace
86 
87 
88 BPrivateScreen*
Get(BWindow * window)89 BPrivateScreen::Get(BWindow* window)
90 {
91 	int32 id = B_MAIN_SCREEN_ID.id;
92 
93 	if (window != NULL) {
94 		BPrivate::AppServerLink link;
95 		link.StartMessage(AS_GET_SCREEN_ID_FROM_WINDOW);
96 		link.Attach<int32>(_get_object_token_(window));
97 
98 		status_t status;
99 		if (link.FlushWithReply(status) == B_OK && status == B_OK)
100 			link.Read<int32>(&id);
101 	}
102 
103 	return _Get(id, false);
104 }
105 
106 
107 BPrivateScreen*
Get(int32 id)108 BPrivateScreen::Get(int32 id)
109 {
110 	return _Get(id, true);
111 }
112 
113 
114 BPrivateScreen*
_Get(int32 id,bool check)115 BPrivateScreen::_Get(int32 id, bool check)
116 {
117 	// Nothing works without an app_server connection
118 	if (be_app == NULL)
119 		return NULL;
120 
121 	Screens* screens = Screens::Default();
122 	AutoLocker<Screens> locker(screens);
123 
124 	// search for the screen ID
125 
126 	for (int32 i = screens->list.CountItems(); i-- > 0;) {
127 		BPrivateScreen* screen = screens->list.ItemAt(i);
128 
129 		if (screen->ID() == id) {
130 			screen->_Acquire();
131 			return screen;
132 		}
133 	}
134 
135 	if (check) {
136 		// check if ID is valid
137 		if (!_IsValid(id))
138 			return NULL;
139 	}
140 
141 	// we need to allocate a new one
142 
143 	BPrivateScreen* screen = new (std::nothrow) BPrivateScreen(id);
144 	if (screen == NULL)
145 		return NULL;
146 
147 	screens->list.AddItem(screen);
148 	return screen;
149 }
150 
151 
152 void
Put(BPrivateScreen * screen)153 BPrivateScreen::Put(BPrivateScreen* screen)
154 {
155 	if (screen == NULL)
156 		return;
157 
158 	Screens* screens = Screens::Default();
159 	AutoLocker<Screens> locker(screens);
160 
161 	if (screen->_Release()) {
162 		if (screen->ID() != B_MAIN_SCREEN_ID.id) {
163 			// we always keep the main screen object around - it will
164 			// never go away, even if you disconnect all monitors.
165 			screens->list.RemoveItem(screen);
166 		}
167 	}
168 }
169 
170 
171 BPrivateScreen*
GetNext(BPrivateScreen * screen)172 BPrivateScreen::GetNext(BPrivateScreen* screen)
173 {
174 	Screens* screens = Screens::Default();
175 	AutoLocker<Screens> locker(screens);
176 
177 	int32 id;
178 	status_t status = screen->GetNextID(id);
179 	if (status != B_OK)
180 		return NULL;
181 
182 	BPrivateScreen* nextScreen = Get(id);
183 	if (nextScreen == NULL)
184 		return NULL;
185 
186 	Put(screen);
187 	return nextScreen;
188 }
189 
190 
191 bool
_IsValid(int32 id)192 BPrivateScreen::_IsValid(int32 id)
193 {
194 	BPrivate::AppServerLink link;
195 	link.StartMessage(AS_VALID_SCREEN_ID);
196 	link.Attach<int32>(id);
197 
198 	status_t status;
199 	if (link.FlushWithReply(status) != B_OK || status < B_OK)
200 		return false;
201 
202 	return true;
203 }
204 
205 
206 //	#pragma mark -
207 
208 
209 color_space
ColorSpace()210 BPrivateScreen::ColorSpace()
211 {
212 	display_mode mode;
213 	if (GetMode(B_CURRENT_WORKSPACE_INDEX, &mode) == B_OK)
214 		return (color_space)mode.space;
215 
216 	return B_NO_COLOR_SPACE;
217 }
218 
219 
220 BRect
Frame()221 BPrivateScreen::Frame()
222 {
223 	if (system_time() > fLastUpdate + 10000) {
224 		// invalidate the settings after 10 msecs
225 		BPrivate::AppServerLink link;
226 		link.StartMessage(AS_GET_SCREEN_FRAME);
227 		link.Attach<int32>(ID());
228 		link.Attach<uint32>(B_CURRENT_WORKSPACE_INDEX);
229 
230 		status_t status = B_ERROR;
231 		if (link.FlushWithReply(status) == B_OK && status == B_OK) {
232 			link.Read<BRect>(&fFrame);
233 			fLastUpdate = system_time();
234 		}
235 	}
236 
237 	return fFrame;
238 }
239 
240 
241 bool
IsValid() const242 BPrivateScreen::IsValid() const
243 {
244 	return BPrivateScreen::_IsValid(ID());
245 }
246 
247 
248 status_t
GetNextID(int32 & id)249 BPrivateScreen::GetNextID(int32& id)
250 {
251 	BPrivate::AppServerLink link;
252 	link.StartMessage(AS_GET_NEXT_SCREEN_ID);
253 	link.Attach<int32>(ID());
254 
255 	status_t status;
256 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
257 		link.Read<int32>(&id);
258 		return B_OK;
259 	}
260 
261 	return status;
262 }
263 
264 
265 status_t
WaitForRetrace(bigtime_t timeout)266 BPrivateScreen::WaitForRetrace(bigtime_t timeout)
267 {
268 	// Get the retrace semaphore if it's the first time
269 	// we are called. Cache the value then.
270 	if (!fRetraceSemValid)
271 		fRetraceSem = _RetraceSemaphore();
272 
273 	if (fRetraceSem < 0) {
274 		// syncing to retrace is not supported by the accelerant
275 		return fRetraceSem;
276 	}
277 
278 	status_t status;
279 	do {
280 		status = acquire_sem_etc(fRetraceSem, 1, B_RELATIVE_TIMEOUT, timeout);
281 	} while (status == B_INTERRUPTED);
282 
283 	return status;
284 }
285 
286 
287 uint8
IndexForColor(uint8 red,uint8 green,uint8 blue,uint8 alpha)288 BPrivateScreen::IndexForColor(uint8 red, uint8 green, uint8 blue, uint8 alpha)
289 {
290 	// Looks like this check is necessary
291 	if (red == B_TRANSPARENT_COLOR.red
292 		&& green == B_TRANSPARENT_COLOR.green
293 		&& blue == B_TRANSPARENT_COLOR.blue
294 		&& alpha == B_TRANSPARENT_COLOR.alpha)
295 		return B_TRANSPARENT_8_BIT;
296 
297 	uint16 index = ((red & 0xf8) << 7) | ((green & 0xf8) << 2) | (blue >> 3);
298 	if (ColorMap())
299 		return fColorMap->index_map[index];
300 
301 	return 0;
302 }
303 
304 
305 rgb_color
ColorForIndex(const uint8 index)306 BPrivateScreen::ColorForIndex(const uint8 index)
307 {
308 	if (ColorMap())
309 		return fColorMap->color_list[index];
310 
311 	return rgb_color();
312 }
313 
314 
315 uint8
InvertIndex(uint8 index)316 BPrivateScreen::InvertIndex(uint8 index)
317 {
318 	if (ColorMap())
319 		return fColorMap->inversion_map[index];
320 
321 	return 0;
322 }
323 
324 
325 const color_map*
ColorMap()326 BPrivateScreen::ColorMap()
327 {
328 	if (fColorMap == NULL) {
329 		Screens* screens = Screens::Default();
330 		AutoLocker<Screens> locker(screens);
331 
332 		if (fColorMap != NULL) {
333 			// someone could have been faster than us
334 			return fColorMap;
335 		}
336 
337 		// TODO: BeOS R5 here gets the colormap pointer
338 		// (with BApplication::ro_offset_to_ptr() ?)
339 		// which is contained in a shared area created by the server.
340 		BPrivate::AppServerLink link;
341 		link.StartMessage(AS_SCREEN_GET_COLORMAP);
342 		link.Attach<int32>(ID());
343 
344 		status_t status;
345 		if (link.FlushWithReply(status) == B_OK && status == B_OK) {
346 			fColorMap = (color_map*)malloc(sizeof(color_map));
347 			fOwnsColorMap = true;
348 			link.Read<color_map>(fColorMap);
349 		}
350 	}
351 
352 	return fColorMap;
353 }
354 
355 
356 status_t
GetBitmap(BBitmap ** _bitmap,bool drawCursor,BRect * bounds)357 BPrivateScreen::GetBitmap(BBitmap**_bitmap, bool drawCursor, BRect* bounds)
358 {
359 	if (_bitmap == NULL)
360 		return B_BAD_VALUE;
361 
362 	BRect rect;
363 	if (bounds != NULL)
364 		rect = *bounds;
365 	else
366 		rect = Frame();
367 
368 	BBitmap* bitmap = new (std::nothrow) BBitmap(rect, ColorSpace());
369 	if (bitmap == NULL)
370 		return B_NO_MEMORY;
371 
372 	status_t status = bitmap->InitCheck();
373 	if (status == B_OK)
374 		status = ReadBitmap(bitmap, drawCursor, &rect);
375 	if (status != B_OK) {
376 		delete bitmap;
377 		return status;
378 	}
379 
380 	*_bitmap = bitmap;
381 	return B_OK;
382 }
383 
384 
385 status_t
ReadBitmap(BBitmap * bitmap,bool drawCursor,BRect * bounds)386 BPrivateScreen::ReadBitmap(BBitmap* bitmap, bool drawCursor, BRect* bounds)
387 {
388 	if (bitmap == NULL)
389 		return B_BAD_VALUE;
390 
391 	BRect rect;
392 	if (bounds != NULL)
393 		rect = *bounds;
394 	else
395 		rect = Frame();
396 
397 	BPrivate::AppServerLink link;
398 	link.StartMessage(AS_READ_BITMAP);
399 	link.Attach<int32>(bitmap->_ServerToken());
400 	link.Attach<bool>(drawCursor);
401 	link.Attach<BRect>(rect);
402 
403 	status_t status = B_ERROR;
404 	if (link.FlushWithReply(status) < B_OK || status != B_OK)
405 		return status;
406 
407 	return B_OK;
408 }
409 
410 
411 rgb_color
DesktopColor(uint32 workspace)412 BPrivateScreen::DesktopColor(uint32 workspace)
413 {
414 	rgb_color color = { 51, 102, 152, 255 };
415 	BPrivate::AppServerLink link;
416 
417 	link.StartMessage(AS_GET_DESKTOP_COLOR);
418 	link.Attach<uint32>(workspace);
419 
420 	int32 code;
421 	if (link.FlushWithReply(code) == B_OK
422 		&& code == B_OK)
423 		link.Read<rgb_color>(&color);
424 
425 	return color;
426 }
427 
428 
429 void
SetDesktopColor(rgb_color color,uint32 workspace,bool makeDefault)430 BPrivateScreen::SetDesktopColor(rgb_color color, uint32 workspace,
431 	bool makeDefault)
432 {
433 	BPrivate::AppServerLink link;
434 
435 	link.StartMessage(AS_SET_DESKTOP_COLOR);
436 	link.Attach<rgb_color>(color);
437 	link.Attach<uint32>(workspace);
438 	link.Attach<bool>(makeDefault);
439 	link.Flush();
440 }
441 
442 
443 status_t
ProposeMode(display_mode * target,const display_mode * low,const display_mode * high)444 BPrivateScreen::ProposeMode(display_mode* target,
445 	const display_mode* low, const display_mode* high)
446 {
447 	// We can't return B_BAD_VALUE here, because it's used to indicate
448 	// that the mode returned is supported, but it doesn't fall
449 	// within the limit (see ProposeMode() documentation)
450 	if (target == NULL || low == NULL || high == NULL)
451 		return B_ERROR;
452 
453 	BPrivate::AppServerLink link;
454 	link.StartMessage(AS_PROPOSE_MODE);
455 	link.Attach<int32>(ID());
456 	link.Attach<display_mode>(*target);
457 	link.Attach<display_mode>(*low);
458 	link.Attach<display_mode>(*high);
459 
460 	status_t status = B_ERROR;
461 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
462 		link.Read<display_mode>(target);
463 
464 		bool withinLimits;
465 		link.Read<bool>(&withinLimits);
466 		if (!withinLimits)
467 			status = B_BAD_VALUE;
468 	}
469 
470 	return status;
471 }
472 
473 
474 status_t
GetModeList(display_mode ** _modeList,uint32 * _count)475 BPrivateScreen::GetModeList(display_mode** _modeList, uint32* _count)
476 {
477 	if (_modeList == NULL || _count == NULL)
478 		return B_BAD_VALUE;
479 
480 	BPrivate::AppServerLink link;
481 	link.StartMessage(AS_GET_MODE_LIST);
482 	link.Attach<int32>(ID());
483 
484 	status_t status = B_ERROR;
485 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
486 		uint32 count;
487 		if (link.Read<uint32>(&count) < B_OK)
488 			return B_ERROR;
489 
490 		// TODO: this could get too big for the link
491 		int32 size = count * sizeof(display_mode);
492 		display_mode* modeList = (display_mode *)malloc(size);
493 		if (modeList == NULL)
494 			return B_NO_MEMORY;
495 
496 		if (link.Read(modeList, size) < B_OK) {
497 			free(modeList);
498 			return B_ERROR;
499 		}
500 
501 		*_modeList = modeList;
502 		*_count = count;
503 	}
504 
505 	return status;
506 }
507 
508 
509 status_t
GetMode(uint32 workspace,display_mode * mode)510 BPrivateScreen::GetMode(uint32 workspace, display_mode *mode)
511 {
512 	if (mode == NULL)
513 		return B_BAD_VALUE;
514 
515 	BPrivate::AppServerLink link;
516 	link.StartMessage(AS_SCREEN_GET_MODE);
517 	link.Attach<int32>(ID());
518 	link.Attach<uint32>(workspace);
519 
520 	status_t status = B_ERROR;
521 	if (link.FlushWithReply(status) != B_OK
522 		|| status != B_OK)
523 		return status;
524 
525 	link.Read<display_mode>(mode);
526 	return B_OK;
527 }
528 
529 
530 status_t
SetMode(uint32 workspace,display_mode * mode,bool makeDefault)531 BPrivateScreen::SetMode(uint32 workspace, display_mode *mode, bool makeDefault)
532 {
533 	if (mode == NULL)
534 		return B_BAD_VALUE;
535 
536 	BPrivate::AppServerLink link;
537 	link.StartMessage(AS_SCREEN_SET_MODE);
538 	link.Attach<int32>(ID());
539 	link.Attach<uint32>(workspace);
540 	link.Attach<display_mode>(*mode);
541 	link.Attach<bool>(makeDefault);
542 
543 	status_t status = B_ERROR;
544 	link.FlushWithReply(status);
545 
546 	return status;
547 }
548 
549 
550 status_t
GetDeviceInfo(accelerant_device_info * info)551 BPrivateScreen::GetDeviceInfo(accelerant_device_info *info)
552 {
553 	if (info == NULL)
554 		return B_BAD_VALUE;
555 
556 	BPrivate::AppServerLink link;
557 	link.StartMessage(AS_GET_ACCELERANT_INFO);
558 	link.Attach<int32>(ID());
559 
560 	status_t status = B_ERROR;
561 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
562 		link.Read<accelerant_device_info>(info);
563 		return B_OK;
564 	}
565 
566 	return status;
567 }
568 
569 
570 status_t
GetMonitorInfo(monitor_info * info)571 BPrivateScreen::GetMonitorInfo(monitor_info* info)
572 {
573 	if (info == NULL)
574 		return B_BAD_VALUE;
575 
576 	BPrivate::AppServerLink link;
577 	link.StartMessage(AS_GET_MONITOR_INFO);
578 	link.Attach<int32>(ID());
579 
580 	status_t status = B_ERROR;
581 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
582 		link.Read<monitor_info>(info);
583 		return B_OK;
584 	}
585 
586 	return status;
587 }
588 
589 
590 status_t
GetPixelClockLimits(display_mode * mode,uint32 * low,uint32 * high)591 BPrivateScreen::GetPixelClockLimits(display_mode *mode, uint32 *low, uint32 *high)
592 {
593 	if (mode == NULL || low == NULL || high == NULL)
594 		return B_BAD_VALUE;
595 
596 	BPrivate::AppServerLink link;
597 	link.StartMessage(AS_GET_PIXEL_CLOCK_LIMITS);
598 	link.Attach<int32>(ID());
599 	link.Attach<display_mode>(*mode);
600 
601 	status_t status;
602 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
603 		link.Read<uint32>(low);
604 		link.Read<uint32>(high);
605 		return B_OK;
606 	}
607 
608 	return status;
609 }
610 
611 
612 status_t
GetTimingConstraints(display_timing_constraints * constraints)613 BPrivateScreen::GetTimingConstraints(display_timing_constraints *constraints)
614 {
615 	if (constraints == NULL)
616 		return B_BAD_VALUE;
617 
618 	BPrivate::AppServerLink link;
619 	link.StartMessage(AS_GET_TIMING_CONSTRAINTS);
620 	link.Attach<int32>(ID());
621 
622 	status_t status = B_ERROR;
623 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
624 		link.Read<display_timing_constraints>(constraints);
625 		return B_OK;
626 	}
627 
628 	return status;
629 }
630 
631 
632 status_t
SetDPMS(uint32 dpmsState)633 BPrivateScreen::SetDPMS(uint32 dpmsState)
634 {
635 	BPrivate::AppServerLink link;
636 	link.StartMessage(AS_SET_DPMS);
637 	link.Attach<int32>(ID());
638 	link.Attach<uint32>(dpmsState);
639 
640 	status_t status = B_ERROR;
641 	link.FlushWithReply(status);
642 
643 	return status;
644 }
645 
646 
647 uint32
DPMSState()648 BPrivateScreen::DPMSState()
649 {
650 	uint32 state = 0;
651 
652 	BPrivate::AppServerLink link;
653 	link.StartMessage(AS_GET_DPMS_STATE);
654 	link.Attach<int32>(ID());
655 
656 	status_t status;
657 	if (link.FlushWithReply(status) == B_OK && status == B_OK)
658 		link.Read<uint32>(&state);
659 
660 	return state;
661 }
662 
663 
664 uint32
DPMSCapabilites()665 BPrivateScreen::DPMSCapabilites()
666 {
667 	uint32 capabilities = 0;
668 
669 	BPrivate::AppServerLink link;
670 	link.StartMessage(AS_GET_DPMS_CAPABILITIES);
671 	link.Attach<int32>(ID());
672 
673 	status_t status;
674 	if (link.FlushWithReply(status) == B_OK && status == B_OK)
675 		link.Read<uint32>(&capabilities);
676 
677 	return capabilities;
678 }
679 
680 
681 status_t
GetBrightness(float * brightness)682 BPrivateScreen::GetBrightness(float* brightness)
683 {
684 	if (brightness == NULL)
685 		return B_BAD_VALUE;
686 
687 	BPrivate::AppServerLink link;
688 	link.StartMessage(AS_SCREEN_GET_BRIGHTNESS);
689 	link.Attach<int32>(ID());
690 
691 	status_t status;
692 	if (link.FlushWithReply(status) == B_OK && status == B_OK)
693 		link.Read<float>(brightness);
694 
695 	return status;
696 }
697 
698 
699 status_t
SetBrightness(float brightness)700 BPrivateScreen::SetBrightness(float brightness)
701 {
702 	BPrivate::AppServerLink link;
703 	link.StartMessage(AS_SCREEN_SET_BRIGHTNESS);
704 	link.Attach<int32>(ID());
705 	link.Attach<float>(brightness);
706 
707 	status_t status = B_ERROR;
708 	link.FlushWithReply(status);
709 
710 	return status;
711 }
712 
713 
714 void *
BaseAddress()715 BPrivateScreen::BaseAddress()
716 {
717 	frame_buffer_config config;
718 	if (_GetFrameBufferConfig(config) != B_OK)
719 		return NULL;
720 
721 	return config.frame_buffer;
722 }
723 
724 
725 uint32
BytesPerRow()726 BPrivateScreen::BytesPerRow()
727 {
728 	frame_buffer_config config;
729 	if (_GetFrameBufferConfig(config) != B_OK)
730 		return 0;
731 
732 	return config.bytes_per_row;
733 }
734 
735 
736 // #pragma mark - private methods
737 
738 
739 void
_Acquire()740 BPrivateScreen::_Acquire()
741 {
742 	fReferenceCount++;
743 
744 	fLastUpdate = 0;
745 		// force an update for the new BScreen object
746 }
747 
748 
749 bool
_Release()750 BPrivateScreen::_Release()
751 {
752 	return --fReferenceCount == 0;
753 }
754 
755 
756 sem_id
_RetraceSemaphore()757 BPrivateScreen::_RetraceSemaphore()
758 {
759 	BPrivate::AppServerLink link;
760 	link.StartMessage(AS_GET_RETRACE_SEMAPHORE);
761 	link.Attach<int32>(ID());
762 
763 	sem_id id = B_BAD_SEM_ID;
764 	status_t status = B_ERROR;
765 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
766 		link.Read<sem_id>(&id);
767 		fRetraceSemValid = true;
768 	}
769 
770 	return id;
771 }
772 
773 
774 status_t
_GetFrameBufferConfig(frame_buffer_config & config)775 BPrivateScreen::_GetFrameBufferConfig(frame_buffer_config& config)
776 {
777 	BPrivate::AppServerLink link;
778 	link.StartMessage(AS_GET_FRAME_BUFFER_CONFIG);
779 	link.Attach<int32>(ID());
780 
781 	status_t status = B_ERROR;
782 	if (link.FlushWithReply(status) == B_OK && status == B_OK) {
783 		link.Read<frame_buffer_config>(&config);
784 		return B_OK;
785 	}
786 
787 	return status;
788 }
789 
790 
BPrivateScreen(int32 id)791 BPrivateScreen::BPrivateScreen(int32 id)
792 	:
793 	fID(id),
794 	fReferenceCount(0),
795 	fColorMap(NULL),
796 	fRetraceSem(-1),
797 	fRetraceSemValid(false),
798 	fOwnsColorMap(false),
799 	fFrame(0, 0, 0, 0),
800 	fLastUpdate(0)
801 {
802 }
803 
804 
~BPrivateScreen()805 BPrivateScreen::~BPrivateScreen()
806 {
807 	if (fOwnsColorMap)
808 		free(fColorMap);
809 }
810