xref: /haiku/src/tests/servers/app/newerClipping/drawing/AccelerantHWInterface.cpp (revision 2f470aec1c92ce6917b8a903e343795dc77af41f)
1 /*
2  * Copyright 2001-2005, Haiku.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Michael Lotz <mmlr@mlotz.ch>
7  *		DarkWyrm <bpmagic@columbus.rr.com>
8  *		Stephan Aßmus <superstippi@gmx.de>
9  */
10 
11 /**	Accelerant based HWInterface implementation */
12 
13 #include <new>
14 #include <malloc.h>
15 #include <stdio.h>
16 #include <string.h>
17 
18 #include <Cursor.h>
19 
20 #include <graphic_driver.h>
21 #include <FindDirectory.h>
22 #include <image.h>
23 #include <dirent.h>
24 #include <sys/ioctl.h>
25 #include <unistd.h>
26 
27 #include "AccelerantHWInterface.h"
28 //#include "AccelerantBuffer.h"
29 //#include "MallocBuffer.h"
30 
31 using std::nothrow;
32 
33 #define DEBUG_DRIVER_MODULE
34 
35 #ifdef DEBUG_DRIVER_MODULE
36 #	include <stdio.h>
37 #	define ATRACE(x) printf x
38 #else
39 #	define ATRACE(x) ;
40 #endif
41 
42 // constructor
43 AccelerantHWInterface::AccelerantHWInterface()
44 	:	//HWInterface(),
45 		fCardFD(-1),
46 		fAccelerantImage(-1),
47 		fAccelerantHook(NULL),
48 		fEngineToken(NULL),
49 		fSyncToken(),
50 
51 		// required hooks
52 		fAccAcquireEngine(NULL),
53 		fAccReleaseEngine(NULL),
54 		fAccSyncToToken(NULL),
55 		fAccGetModeCount(NULL),
56 		fAccGetModeList(NULL),
57 		fAccGetFrameBufferConfig(NULL),
58 		fAccSetDisplayMode(NULL),
59 		fAccGetDisplayMode(NULL),
60 		fAccGetPixelClockLimits(NULL),
61 
62 		// optional accelerant hooks
63 		fAccGetTimingConstraints(NULL),
64 		fAccProposeDisplayMode(NULL),
65 		fAccFillRect(NULL),
66 		fAccInvertRect(NULL),
67 		fAccScreenBlit(NULL),
68 		fAccSetCursorShape(NULL),
69 		fAccMoveCursor(NULL),
70 		fAccShowCursor(NULL)//,
71 
72 		// dpms hooks
73 /*		fAccDPMSCapabilities(NULL),
74 		fAccDPMSMode(NULL),
75 		fAccSetDPMSMode(NULL),
76 
77 		fModeCount(0),
78 		fModeList(NULL),*/
79 
80 //		fBackBuffer(NULL),
81 //		fFrontBuffer(new(nothrow) AccelerantBuffer())
82 {
83 /*	fDisplayMode.virtual_width = 640;
84 	fDisplayMode.virtual_height = 480;
85 	fDisplayMode.space = B_RGB32;*/
86 
87 	// NOTE: I have no clue what I'm doing here.
88 //	fSyncToken.counter = 0;
89 //	fSyncToken.engine_id = 0;
90 	memset(&fSyncToken, 0, sizeof(sync_token));
91 }
92 
93 // destructor
94 AccelerantHWInterface::~AccelerantHWInterface()
95 {
96 //	delete fBackBuffer;
97 //	delete fFrontBuffer;
98 //	delete[] fModeList;
99 }
100 
101 
102 /*!
103 	\brief Opens the first available graphics device and initializes it
104 	\return B_OK on success or an appropriate error message on failure.
105 */
106 status_t
107 AccelerantHWInterface::Initialize()
108 {
109 	status_t ret = B_OK;//HWInterface::Initialize();
110 	if (ret >= B_OK) {
111 		for (int32 i = 1; fCardFD != B_ENTRY_NOT_FOUND; i++) {
112 			fCardFD = _OpenGraphicsDevice(i);
113 			if (fCardFD < 0) {
114 				ATRACE(("Failed to open graphics device\n"));
115 				continue;
116 			}
117 
118 			if (_OpenAccelerant(fCardFD) == B_OK)
119 				break;
120 
121 			close(fCardFD);
122 			// _OpenAccelerant() failed, try to open next graphics card
123 		}
124 
125 		return fCardFD >= 0 ? B_OK : fCardFD;
126 	}
127 	return ret;
128 }
129 
130 
131 /*!
132 	\brief Opens a graphics device for read-write access
133 	\param deviceNumber Number identifying which graphics card to open (1 for first card)
134 	\return The file descriptor for the opened graphics device
135 
136 	The deviceNumber is relative to the number of graphics devices that can be successfully
137 	opened.  One represents the first card that can be successfully opened (not necessarily
138 	the first one listed in the directory).
139 	Graphics drivers must be able to be opened more than once, so we really get
140 	the first working entry.
141 */
142 int
143 AccelerantHWInterface::_OpenGraphicsDevice(int deviceNumber)
144 {
145 	DIR *directory = opendir("/dev/graphics");
146 	if (!directory)
147 		return -1;
148 
149 	// ToDo: the former R5 "stub" driver is called "vesa" under Haiku; however,
150 	//	we do not need to avoid this driver this way when is has been ported
151 	//	to the new driver architecture - the special case here can then be
152 	//	removed.
153 	int count = 0;
154 	struct dirent *entry;
155 	int current_card_fd = -1;
156 	char path[PATH_MAX];
157 	while (count < deviceNumber && (entry = readdir(directory)) != NULL) {
158 		if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..") ||
159 			!strcmp(entry->d_name, "stub") || !strcmp(entry->d_name, "vesa"))
160 			continue;
161 
162 		if (current_card_fd >= 0) {
163 			close(current_card_fd);
164 			current_card_fd = -1;
165 		}
166 
167 		sprintf(path, "/dev/graphics/%s", entry->d_name);
168 		current_card_fd = open(path, B_READ_WRITE);
169 		if (current_card_fd >= 0)
170 			count++;
171 	}
172 
173 	// Open VESA driver if we were not able to get a better one
174 	if (count < deviceNumber) {
175 		if (deviceNumber == 1) {
176 			sprintf(path, "/dev/graphics/vesa");
177 			current_card_fd = open(path, B_READ_WRITE);
178 		} else {
179 			close(current_card_fd);
180 			current_card_fd = B_ENTRY_NOT_FOUND;
181 		}
182 	}
183 
184 	fCardNameInDevFS = entry->d_name;
185 
186 	return current_card_fd;
187 }
188 
189 
190 status_t
191 AccelerantHWInterface::_OpenAccelerant(int device)
192 {
193 	char signature[1024];
194 	if (ioctl(device, B_GET_ACCELERANT_SIGNATURE,
195 			&signature, sizeof(signature)) != B_OK)
196 		return B_ERROR;
197 
198 	ATRACE(("accelerant signature is: %s\n", signature));
199 
200 	struct stat accelerant_stat;
201 	const static directory_which dirs[] = {
202 		B_USER_ADDONS_DIRECTORY,
203 		B_COMMON_ADDONS_DIRECTORY,
204 		B_BEOS_ADDONS_DIRECTORY
205 	};
206 
207 	fAccelerantImage = -1;
208 
209 	for (int32 i = 0; i < 3; i++) {
210 		char path[PATH_MAX];
211 		if (find_directory(dirs[i], -1, false, path, PATH_MAX) != B_OK)
212 			continue;
213 
214 		strcat(path, "/accelerants/");
215 		strcat(path, signature);
216 		if (stat(path, &accelerant_stat) != 0)
217 			continue;
218 
219 		fAccelerantImage = load_add_on(path);
220 		if (fAccelerantImage >= 0) {
221 			if (get_image_symbol(fAccelerantImage, B_ACCELERANT_ENTRY_POINT,
222 				B_SYMBOL_TYPE_ANY, (void**)(&fAccelerantHook)) != B_OK ) {
223 				ATRACE(("unable to get B_ACCELERANT_ENTRY_POINT\n"));
224 				unload_add_on(fAccelerantImage);
225 				fAccelerantImage = -1;
226 				return B_ERROR;
227 			}
228 
229 
230 			accelerant_clone_info_size cloneInfoSize;
231 			cloneInfoSize = (accelerant_clone_info_size)fAccelerantHook(B_ACCELERANT_CLONE_INFO_SIZE, NULL);
232 			if (!cloneInfoSize) {
233 				ATRACE(("unable to get B_ACCELERANT_CLONE_INFO_SIZE (%s)\n", path));
234 				unload_add_on(fAccelerantImage);
235 				fAccelerantImage = -1;
236 				return B_ERROR;
237 			}
238 
239 			ssize_t cloneSize = cloneInfoSize();
240 			void* cloneInfoData = malloc(cloneSize);
241 
242 //			get_accelerant_clone_info getCloneInfo;
243 //			getCloneInfo = (get_accelerant_clone_info)fAccelerantHook(B_GET_ACCELERANT_CLONE_INFO, NULL);
244 //			if (!getCloneInfo) {
245 //				ATRACE(("unable to get B_GET_ACCELERANT_CLONE_INFO (%s)\n", path));
246 //				unload_add_on(fAccelerantImage);
247 //				fAccelerantImage = -1;
248 //				return B_ERROR;
249 //			}
250 //			printf("getCloneInfo: %p\n", getCloneInfo);
251 //
252 //			getCloneInfo(cloneInfoData);
253 // TODO: this is what works for the ATI Radeon driver...
254 sprintf((char*)cloneInfoData, "graphics/%s", fCardNameInDevFS.String());
255 
256 			clone_accelerant cloneAccelerant;
257 			cloneAccelerant = (clone_accelerant)fAccelerantHook(B_CLONE_ACCELERANT, NULL);
258 			if (!cloneAccelerant) {
259 				ATRACE(("unable to get B_CLONE_ACCELERANT\n"));
260 				unload_add_on(fAccelerantImage);
261 				fAccelerantImage = -1;
262 				return B_ERROR;
263 			}
264 			status_t ret = cloneAccelerant(cloneInfoData);
265 			if (ret  != B_OK) {
266 				ATRACE(("Cloning accelerant unsuccessful: %s\n", strerror(ret)));
267 				unload_add_on(fAccelerantImage);
268 				fAccelerantImage = -1;
269 				return B_ERROR;
270 			}
271 
272 			break;
273 		}
274 	}
275 
276 	if (fAccelerantImage < B_OK)
277 		return B_ERROR;
278 
279 	if (_SetupDefaultHooks() != B_OK) {
280 		ATRACE(("cannot setup default hooks\n"));
281 
282 		uninit_accelerant uninitAccelerant = (uninit_accelerant)
283 			fAccelerantHook(B_UNINIT_ACCELERANT, NULL);
284 		if (uninitAccelerant != NULL)
285 			uninitAccelerant();
286 
287 		unload_add_on(fAccelerantImage);
288 		return B_ERROR;
289 	}
290 
291 	return B_OK;
292 }
293 
294 
295 status_t
296 AccelerantHWInterface::_SetupDefaultHooks()
297 {
298 	// required
299 	fAccAcquireEngine = (acquire_engine)fAccelerantHook(B_ACQUIRE_ENGINE, NULL);
300 	fAccReleaseEngine = (release_engine)fAccelerantHook(B_RELEASE_ENGINE, NULL);
301 	fAccSyncToToken = (sync_to_token)fAccelerantHook(B_SYNC_TO_TOKEN, NULL);
302 	fAccGetModeCount = (accelerant_mode_count)fAccelerantHook(B_ACCELERANT_MODE_COUNT, NULL);
303 	fAccGetModeList = (get_mode_list)fAccelerantHook(B_GET_MODE_LIST, NULL);
304 	fAccGetFrameBufferConfig = (get_frame_buffer_config)fAccelerantHook(B_GET_FRAME_BUFFER_CONFIG, NULL);
305 	fAccSetDisplayMode = (set_display_mode)fAccelerantHook(B_SET_DISPLAY_MODE, NULL);
306 	fAccGetDisplayMode = (get_display_mode)fAccelerantHook(B_GET_DISPLAY_MODE, NULL);
307 	fAccGetPixelClockLimits = (get_pixel_clock_limits)fAccelerantHook(B_GET_PIXEL_CLOCK_LIMITS, NULL);
308 
309 	if (!fAccAcquireEngine || !fAccReleaseEngine || !fAccGetFrameBufferConfig
310 		|| !fAccGetModeCount || !fAccGetModeList || !fAccSetDisplayMode
311 		|| !fAccGetDisplayMode || !fAccGetPixelClockLimits) {
312 		return B_ERROR;
313 	}
314 
315 	// optional
316 	fAccGetTimingConstraints = (get_timing_constraints)fAccelerantHook(B_GET_TIMING_CONSTRAINTS, NULL);
317 	fAccProposeDisplayMode = (propose_display_mode)fAccelerantHook(B_PROPOSE_DISPLAY_MODE, NULL);
318 
319 	// cursor
320 	fAccSetCursorShape = (set_cursor_shape)fAccelerantHook(B_SET_CURSOR_SHAPE, NULL);
321 	fAccMoveCursor = (move_cursor)fAccelerantHook(B_MOVE_CURSOR, NULL);
322 	fAccShowCursor = (show_cursor)fAccelerantHook(B_SHOW_CURSOR, NULL);
323 
324 	// dpms
325 //	fAccDPMSCapabilities = (dpms_capabilities)fAccelerantHook(B_DPMS_CAPABILITIES, NULL);
326 //	fAccDPMSMode = (dpms_mode)fAccelerantHook(B_DPMS_MODE, NULL);
327 //	fAccSetDPMSMode = (set_dpms_mode)fAccelerantHook(B_SET_DPMS_MODE, NULL);
328 
329 	// update acceleration hooks
330 	// TODO: would actually have to pass a valid display_mode!
331 	fAccFillRect = (fill_rectangle)fAccelerantHook(B_FILL_RECTANGLE, NULL);
332 	fAccInvertRect = (invert_rectangle)fAccelerantHook(B_INVERT_RECTANGLE, NULL);
333 	fAccScreenBlit = (screen_to_screen_blit)fAccelerantHook(B_SCREEN_TO_SCREEN_BLIT, NULL);
334 
335 	return B_OK;
336 }
337 
338 // Shutdown
339 status_t
340 AccelerantHWInterface::Shutdown()
341 {
342 	if (fAccelerantHook) {
343 		uninit_accelerant UninitAccelerant = (uninit_accelerant)fAccelerantHook(B_UNINIT_ACCELERANT, NULL);
344 		if (UninitAccelerant)
345 			UninitAccelerant();
346 	}
347 
348 	if (fAccelerantImage >= 0)
349 		unload_add_on(fAccelerantImage);
350 
351 	if (fCardFD >= 0)
352 		close(fCardFD);
353 
354 	return B_OK;
355 }
356 /*
357 // SetMode
358 status_t
359 AccelerantHWInterface::SetMode(const display_mode &mode)
360 {
361 	AutoWriteLocker _(this);
362 	// TODO: There are places this function can fail,
363 	// maybe it needs to roll back changes in case of an
364 	// error.
365 
366 	// prevent from doing the unnecessary
367 	if (fModeCount > 0 && fBackBuffer && fFrontBuffer
368 		&& fDisplayMode == mode) {
369 		// TODO: better comparison of display modes
370 		return B_OK;
371 	}
372 
373 	// just try to set the mode - we let the graphics driver
374 	// approve or deny the request, as it should know best
375 
376 	fDisplayMode = mode;
377 
378 	if (fAccSetDisplayMode(&fDisplayMode) != B_OK) {
379 		ATRACE(("setting display mode failed\n"));
380 		fAccGetDisplayMode(&fDisplayMode);
381 			// We just keep the current mode and continue.
382 			// Note, on startup, this may be different from
383 			// what we think is the current display mode
384 	}
385 
386 	// update frontbuffer
387 	fFrontBuffer->SetDisplayMode(fDisplayMode);
388 	if (_UpdateFrameBufferConfig() != B_OK)
389 		return B_ERROR;
390 
391 	// Update the frame buffer used by the on-screen KDL
392 #ifdef __HAIKU__
393 	uint32 depth = (fFrameBufferConfig.bytes_per_row / fDisplayMode.virtual_width) << 3;
394 	if (fDisplayMode.space == B_RGB15)
395 		depth = 15;
396 
397 	_kern_frame_buffer_update(fFrameBufferConfig.frame_buffer,
398 		fDisplayMode.virtual_width, fDisplayMode.virtual_height,
399 		depth, fFrameBufferConfig.bytes_per_row);
400 #endif
401 
402 	// update backbuffer if neccessary
403 	if (!fBackBuffer || fBackBuffer->Width() != fDisplayMode.virtual_width
404 		|| fBackBuffer->Height() != fDisplayMode.virtual_height) {
405 		// NOTE: backbuffer is always B_RGBA32, this simplifies the
406 		// drawing backend implementation tremendously for the time
407 		// being. The color space conversion is handled in CopyBackToFront()
408 
409 		delete fBackBuffer;
410 		fBackBuffer = NULL;
411 
412 		// TODO: Above not true anymore for single buffered mode!!!
413 		// -> fall back to double buffer for fDisplayMode.space != B_RGB32
414 		// as intermediate solution...
415 		bool doubleBuffered = HWInterface::IsDoubleBuffered();
416 		if ((color_space)fDisplayMode.space != B_RGB32 &&
417 			(color_space)fDisplayMode.space != B_RGBA32)
418 			doubleBuffered = true;
419 
420 		if (doubleBuffered) {
421 			fBackBuffer = new(nothrow) MallocBuffer(fDisplayMode.virtual_width,
422 													fDisplayMode.virtual_height);
423 
424 			status_t ret = fBackBuffer ? fBackBuffer->InitCheck() : B_NO_MEMORY;
425 			if (ret < B_OK) {
426 				delete fBackBuffer;
427 				fBackBuffer = NULL;
428 				return ret;
429 			}
430 			// clear out backbuffer, alpha is 255 this way
431 			memset(fBackBuffer->Bits(), 255, fBackBuffer->BitsLength());
432 		}
433 	}
434 
435 	// update acceleration hooks
436 	fAccFillRect = (fill_rectangle)fAccelerantHook(B_FILL_RECTANGLE, (void *)&fDisplayMode);
437 	fAccInvertRect = (invert_rectangle)fAccelerantHook(B_INVERT_RECTANGLE,
438 		(void *)&fDisplayMode);
439 	fAccScreenBlit = (screen_to_screen_blit)fAccelerantHook(B_SCREEN_TO_SCREEN_BLIT,
440 		(void *)&fDisplayMode);
441 
442 	return B_OK;
443 }
444 
445 
446 void
447 AccelerantHWInterface::GetMode(display_mode *mode)
448 {
449 	if (mode && ReadLock()) {
450 		*mode = fDisplayMode;
451 		ReadUnlock();
452 	}
453 }
454 
455 
456 status_t
457 AccelerantHWInterface::_UpdateModeList()
458 {
459 	fModeCount = fAccGetModeCount();
460 	if (fModeCount <= 0)
461 		return B_ERROR;
462 
463 	delete[] fModeList;
464 	fModeList = new(nothrow) display_mode[fModeCount];
465 	if (!fModeList)
466 		return B_NO_MEMORY;
467 
468 	if (fAccGetModeList(fModeList) != B_OK) {
469 		ATRACE(("unable to get mode list\n"));
470 		return B_ERROR;
471 	}
472 
473 	return B_OK;
474 }
475 
476 
477 status_t
478 AccelerantHWInterface::_UpdateFrameBufferConfig()
479 {
480 	if (fAccGetFrameBufferConfig(&fFrameBufferConfig) != B_OK) {
481 		ATRACE(("unable to get frame buffer config\n"));
482 		return B_ERROR;
483 	}
484 
485 	fFrontBuffer->SetFrameBufferConfig(fFrameBufferConfig);
486 	return B_OK;
487 }
488 
489 
490 status_t
491 AccelerantHWInterface::GetDeviceInfo(accelerant_device_info *info)
492 {
493 	get_accelerant_device_info GetAccelerantDeviceInfo = (get_accelerant_device_info)fAccelerantHook(B_GET_ACCELERANT_DEVICE_INFO, NULL);
494 	if (!GetAccelerantDeviceInfo) {
495 		ATRACE(("No B_GET_ACCELERANT_DEVICE_INFO hook found\n"));
496 		return B_UNSUPPORTED;
497 	}
498 
499 	return GetAccelerantDeviceInfo(info);
500 }
501 
502 
503 status_t
504 AccelerantHWInterface::GetFrameBufferConfig(frame_buffer_config& config)
505 {
506 	config = fFrameBufferConfig;
507 	return B_OK;
508 }
509 
510 
511 status_t
512 AccelerantHWInterface::GetModeList(display_mode** modes, uint32 *count)
513 {
514 	AutoReadLocker _(this);
515 
516 	if (!count || !modes)
517 		return B_BAD_VALUE;
518 
519 	status_t ret = fModeList ? B_OK : _UpdateModeList();
520 
521 	if (ret >= B_OK) {
522 		*modes = new(nothrow) display_mode[fModeCount];
523 		if (*modes) {
524 			*count = fModeCount;
525 			memcpy(*modes, fModeList, sizeof(display_mode) * fModeCount);
526 		} else {
527 			*count = 0;
528 			ret = B_NO_MEMORY;
529 		}
530 	}
531 	return ret;
532 }
533 
534 status_t
535 AccelerantHWInterface::GetPixelClockLimits(display_mode *mode, uint32 *low, uint32 *high)
536 {
537 	AutoReadLocker _(this);
538 
539 	if (!mode || !low || !high)
540 		return B_BAD_VALUE;
541 
542 	return fAccGetPixelClockLimits(mode, low, high);
543 }
544 
545 status_t
546 AccelerantHWInterface::GetTimingConstraints(display_timing_constraints *dtc)
547 {
548 	AutoReadLocker _(this);
549 
550 	if (!dtc)
551 		return B_BAD_VALUE;
552 
553 	if (fAccGetTimingConstraints)
554 		return fAccGetTimingConstraints(dtc);
555 
556 	return B_UNSUPPORTED;
557 }
558 
559 status_t
560 AccelerantHWInterface::ProposeMode(display_mode *candidate, const display_mode *low, const display_mode *high)
561 {
562 	AutoReadLocker _(this);
563 
564 	if (!candidate || !low || !high)
565 		return B_BAD_VALUE;
566 
567 	if (!fAccProposeDisplayMode)
568 		return B_UNSUPPORTED;
569 
570 	// avoid const issues
571 	display_mode this_high, this_low;
572 	this_high = *high;
573 	this_low = *low;
574 
575 	return fAccProposeDisplayMode(candidate, &this_low, &this_high);
576 }
577 
578 // RetraceSemaphore
579 sem_id
580 AccelerantHWInterface::RetraceSemaphore()
581 {
582 	accelerant_retrace_semaphore AccelerantRetraceSemaphore = (accelerant_retrace_semaphore)fAccelerantHook(B_ACCELERANT_RETRACE_SEMAPHORE, NULL);
583 	if (!AccelerantRetraceSemaphore)
584 		return B_UNSUPPORTED;
585 
586 	return AccelerantRetraceSemaphore();
587 }
588 
589 // WaitForRetrace
590 status_t
591 AccelerantHWInterface::WaitForRetrace(bigtime_t timeout)
592 {
593 	AutoReadLocker _(this);
594 
595 	accelerant_retrace_semaphore AccelerantRetraceSemaphore = (accelerant_retrace_semaphore)fAccelerantHook(B_ACCELERANT_RETRACE_SEMAPHORE, NULL);
596 	if (!AccelerantRetraceSemaphore)
597 		return B_UNSUPPORTED;
598 
599 	sem_id sem = AccelerantRetraceSemaphore();
600 	if (sem < 0)
601 		return B_ERROR;
602 
603 	return acquire_sem_etc(sem, 1, B_RELATIVE_TIMEOUT, timeout);
604 }
605 
606 // SetDPMSMode
607 status_t
608 AccelerantHWInterface::SetDPMSMode(const uint32 &state)
609 {
610 	AutoWriteLocker _(this);
611 
612 	if (!fAccSetDPMSMode)
613 		return B_UNSUPPORTED;
614 
615 	return fAccSetDPMSMode(state);
616 }
617 
618 // DPMSMode
619 uint32
620 AccelerantHWInterface::DPMSMode()
621 {
622 	AutoReadLocker _(this);
623 
624 	if (!fAccDPMSMode)
625 		return B_UNSUPPORTED;
626 
627 	return fAccDPMSMode();
628 }
629 
630 // DPMSCapabilities
631 uint32
632 AccelerantHWInterface::DPMSCapabilities()
633 {
634 	AutoReadLocker _(this);
635 
636 	if (!fAccDPMSCapabilities)
637 		return B_UNSUPPORTED;
638 
639 	return fAccDPMSCapabilities();
640 }
641 */
642 // AvailableHardwareAcceleration
643 uint32
644 AccelerantHWInterface::AvailableHWAcceleration() const
645 {
646 	uint32 flags = 0;
647 
648 /*	if (!IsDoubleBuffered()) {
649 		if (fAccScreenBlit)
650 			flags |= HW_ACC_COPY_REGION;
651 		if (fAccFillRect)
652 			flags |= HW_ACC_FILL_REGION;
653 		if (fAccInvertRect)
654 			flags |= HW_ACC_INVERT_REGION;
655 	}*/
656 
657 	return flags;
658 }
659 
660 // CopyRegion
661 void
662 AccelerantHWInterface::CopyRegion(const clipping_rect* sortedRectList,
663 								  uint32 count, int32 xOffset, int32 yOffset)
664 {
665 	if (fAccScreenBlit && fAccAcquireEngine) {
666 		if (fAccAcquireEngine(B_2D_ACCELERATION, 0xff, &fSyncToken, &fEngineToken) >= B_OK) {
667 
668 			// convert the rects
669 			blit_params* params = new blit_params[count];
670 			for (uint32 i = 0; i < count; i++) {
671 				params[i].src_left = (uint16)sortedRectList[i].left;
672 				params[i].src_top = (uint16)sortedRectList[i].top;
673 
674 				params[i].dest_left = (uint16)sortedRectList[i].left + xOffset;
675 				params[i].dest_top = (uint16)sortedRectList[i].top + yOffset;
676 
677 				// NOTE: width and height are expressed as distance, not pixel count!
678 				params[i].width = (uint16)(sortedRectList[i].right - sortedRectList[i].left);
679 				params[i].height = (uint16)(sortedRectList[i].bottom - sortedRectList[i].top);
680 			}
681 
682 			// go
683 			fAccScreenBlit(fEngineToken, params, count);
684 
685 			// done
686 			if (fAccReleaseEngine)
687 				fAccReleaseEngine(fEngineToken, &fSyncToken);
688 
689 			// sync
690 			if (fAccSyncToToken)
691 				fAccSyncToToken(&fSyncToken);
692 
693 			delete[] params;
694 		}
695 	}
696 }
697 
698 // FillRegion
699 void
700 AccelerantHWInterface::FillRegion(/*const*/ BRegion& region, const rgb_color& color)
701 {
702 	if (fAccFillRect && fAccAcquireEngine) {
703 		if (fAccAcquireEngine(B_2D_ACCELERATION, 0xff, &fSyncToken, &fEngineToken) >= B_OK) {
704 
705 			// convert the region
706 			uint32 count;
707 			fill_rect_params* fillParams;
708 			_RegionToRectParams(&region, &fillParams, &count);
709 
710 			// go
711 			fAccFillRect(fEngineToken, _NativeColor(color), fillParams, count);
712 
713 			// done
714 			if (fAccReleaseEngine)
715 				fAccReleaseEngine(fEngineToken, &fSyncToken);
716 
717 			// sync
718 			if (fAccSyncToToken)
719 				fAccSyncToToken(&fSyncToken);
720 
721 			delete[] fillParams;
722 		}
723 	}
724 }
725 
726 // InvertRegion
727 void
728 AccelerantHWInterface::InvertRegion(/*const*/ BRegion& region)
729 {
730 	if (fAccInvertRect && fAccAcquireEngine) {
731 		if (fAccAcquireEngine(B_2D_ACCELERATION, 0xff, &fSyncToken, &fEngineToken) >= B_OK) {
732 
733 			// convert the region
734 			uint32 count;
735 			fill_rect_params* fillParams;
736 			_RegionToRectParams(&region, &fillParams, &count);
737 
738 			// go
739 			fAccInvertRect(fEngineToken, fillParams, count);
740 
741 			// done
742 			if (fAccReleaseEngine)
743 				fAccReleaseEngine(fEngineToken, &fSyncToken);
744 
745 			// sync
746 			if (fAccSyncToToken)
747 				fAccSyncToToken(&fSyncToken);
748 
749 			delete[] fillParams;
750 		} else {
751 			fprintf(stderr, "AcquireEngine failed!\n");
752 		}
753 	} else {
754 		fprintf(stderr, "AccelerantHWInterface::InvertRegion() called, but hook not available!\n");
755 	}
756 }
757 /*
758 // SetCursor
759 void
760 AccelerantHWInterface::SetCursor(ServerCursor* cursor)
761 {
762 	HWInterface::SetCursor(cursor);
763 //	if (WriteLock()) {
764 		// TODO: implement setting the hard ware cursor
765 		// NOTE: cursor should be always B_RGBA32
766 		// NOTE: The HWInterface implementation should
767 		// still be called, since it takes ownership of
768 		// the cursor.
769 //		WriteUnlock();
770 //	}
771 }
772 
773 // SetCursorVisible
774 void
775 AccelerantHWInterface::SetCursorVisible(bool visible)
776 {
777 	HWInterface::SetCursorVisible(visible);
778 //	if (WriteLock()) {
779 		// TODO: update graphics hardware
780 //		WriteUnlock();
781 //	}
782 }
783 
784 // MoveCursorTo
785 void
786 AccelerantHWInterface::MoveCursorTo(const float& x, const float& y)
787 {
788 	HWInterface::MoveCursorTo(x, y);
789 //	if (WriteLock()) {
790 		// TODO: update graphics hardware
791 //		WriteUnlock();
792 //	}
793 }
794 
795 // FrontBuffer
796 RenderingBuffer *
797 AccelerantHWInterface::FrontBuffer() const
798 {
799 	if (!fModeList)
800 		return NULL;
801 
802 	return fFrontBuffer;
803 }
804 
805 // BackBuffer
806 RenderingBuffer *
807 AccelerantHWInterface::BackBuffer() const
808 {
809 	if (!fModeList)
810 		return NULL;
811 
812 	return fBackBuffer;
813 }
814 
815 // IsDoubleBuffered
816 bool
817 AccelerantHWInterface::IsDoubleBuffered() const
818 {
819 	if (fModeList)
820 		return fBackBuffer != NULL;
821 
822 	return HWInterface::IsDoubleBuffered();
823 }
824 
825 // _DrawCursor
826 void
827 AccelerantHWInterface::_DrawCursor(BRect area) const
828 {
829 	// use the default implementation for now,
830 	// until we have a hardware cursor
831 	HWInterface::_DrawCursor(area);
832 	// TODO: this would only be called, if we don't have
833 	// a hardware cursor for some reason
834 }
835 */
836 // _RegionToRectParams
837 void
838 AccelerantHWInterface::_RegionToRectParams(/*const*/ BRegion* region,
839 										   fill_rect_params** params,
840 										   uint32* count) const
841 {
842 	*count = region->CountRects();
843 	*params = new fill_rect_params[*count];
844 
845 	for (uint32 i = 0; i < *count; i++) {
846 		clipping_rect r = region->RectAtInt(i);
847 		(*params)[i].left = (uint16)r.left;
848 		(*params)[i].top = (uint16)r.top;
849 		(*params)[i].right = (uint16)r.right;
850 		(*params)[i].bottom = (uint16)r.bottom;
851 	}
852 }
853 
854 // _NativeColor
855 uint32
856 AccelerantHWInterface::_NativeColor(const rgb_color& c) const
857 {
858 	// NOTE: This functions looks somehow suspicios to me.
859 	// It assumes that all graphics cards have the same native endianess, no?
860 /*	switch (fDisplayMode.space) {
861 		case B_CMAP8:
862 		case B_GRAY8:
863 			return color.GetColor8();
864 
865 		case B_RGB15_BIG:
866 		case B_RGBA15_BIG:
867 		case B_RGB15_LITTLE:
868 		case B_RGBA15_LITTLE:
869 			return color.GetColor15();
870 
871 		case B_RGB16_BIG:
872 		case B_RGB16_LITTLE:
873 			return color.GetColor16();
874 
875 		case B_RGB32_BIG:
876 		case B_RGBA32_BIG:
877 		case B_RGB32_LITTLE:
878 		case B_RGBA32_LITTLE: {
879 			rgb_color c = color.GetColor32();
880 			uint32 native = (c.alpha << 24) |
881 							(c.red << 16) |
882 							(c.green << 8) |
883 							(c.blue);
884 			return native;
885 		}
886 	}
887 	return 0;*/
888 	uint32 native = (c.alpha << 24) | (c.red << 16) | (c.green << 8) | (c.blue);
889 	return native;
890 }
891