xref: /haiku/src/tests/servers/app/newerClipping/drawing/AccelerantHWInterface.cpp (revision 225b6382637a7346d5378ee45a6581b4e2616055)
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_NONPACKAGED_ADDONS_DIRECTORY,
203 		B_USER_ADDONS_DIRECTORY,
204 		B_COMMON_NONPACKAGED_ADDONS_DIRECTORY,
205 		B_COMMON_ADDONS_DIRECTORY,
206 		B_SYSTEM_ADDONS_DIRECTORY
207 	};
208 
209 	fAccelerantImage = -1;
210 
211 	for (int32 i = 0; i < sizeof(dirs) / sizeof(directory_which); i++) {
212 		char path[PATH_MAX];
213 		if (find_directory(dirs[i], -1, false, path, PATH_MAX) != B_OK)
214 			continue;
215 
216 		strcat(path, "/accelerants/");
217 		strcat(path, signature);
218 		if (stat(path, &accelerant_stat) != 0)
219 			continue;
220 
221 		fAccelerantImage = load_add_on(path);
222 		if (fAccelerantImage >= 0) {
223 			if (get_image_symbol(fAccelerantImage, B_ACCELERANT_ENTRY_POINT,
224 				B_SYMBOL_TYPE_ANY, (void**)(&fAccelerantHook)) != B_OK ) {
225 				ATRACE(("unable to get B_ACCELERANT_ENTRY_POINT\n"));
226 				unload_add_on(fAccelerantImage);
227 				fAccelerantImage = -1;
228 				return B_ERROR;
229 			}
230 
231 
232 			accelerant_clone_info_size cloneInfoSize;
233 			cloneInfoSize = (accelerant_clone_info_size)fAccelerantHook(B_ACCELERANT_CLONE_INFO_SIZE, NULL);
234 			if (!cloneInfoSize) {
235 				ATRACE(("unable to get B_ACCELERANT_CLONE_INFO_SIZE (%s)\n", path));
236 				unload_add_on(fAccelerantImage);
237 				fAccelerantImage = -1;
238 				return B_ERROR;
239 			}
240 
241 			ssize_t cloneSize = cloneInfoSize();
242 			void* cloneInfoData = malloc(cloneSize);
243 
244 //			get_accelerant_clone_info getCloneInfo;
245 //			getCloneInfo = (get_accelerant_clone_info)fAccelerantHook(B_GET_ACCELERANT_CLONE_INFO, NULL);
246 //			if (!getCloneInfo) {
247 //				ATRACE(("unable to get B_GET_ACCELERANT_CLONE_INFO (%s)\n", path));
248 //				unload_add_on(fAccelerantImage);
249 //				fAccelerantImage = -1;
250 //				return B_ERROR;
251 //			}
252 //			printf("getCloneInfo: %p\n", getCloneInfo);
253 //
254 //			getCloneInfo(cloneInfoData);
255 // TODO: this is what works for the ATI Radeon driver...
256 sprintf((char*)cloneInfoData, "graphics/%s", fCardNameInDevFS.String());
257 
258 			clone_accelerant cloneAccelerant;
259 			cloneAccelerant = (clone_accelerant)fAccelerantHook(B_CLONE_ACCELERANT, NULL);
260 			if (!cloneAccelerant) {
261 				ATRACE(("unable to get B_CLONE_ACCELERANT\n"));
262 				unload_add_on(fAccelerantImage);
263 				fAccelerantImage = -1;
264 				return B_ERROR;
265 			}
266 			status_t ret = cloneAccelerant(cloneInfoData);
267 			if (ret  != B_OK) {
268 				ATRACE(("Cloning accelerant unsuccessful: %s\n", strerror(ret)));
269 				unload_add_on(fAccelerantImage);
270 				fAccelerantImage = -1;
271 				return B_ERROR;
272 			}
273 
274 			break;
275 		}
276 	}
277 
278 	if (fAccelerantImage < B_OK)
279 		return B_ERROR;
280 
281 	if (_SetupDefaultHooks() != B_OK) {
282 		ATRACE(("cannot setup default hooks\n"));
283 
284 		uninit_accelerant uninitAccelerant = (uninit_accelerant)
285 			fAccelerantHook(B_UNINIT_ACCELERANT, NULL);
286 		if (uninitAccelerant != NULL)
287 			uninitAccelerant();
288 
289 		unload_add_on(fAccelerantImage);
290 		return B_ERROR;
291 	}
292 
293 	return B_OK;
294 }
295 
296 
297 status_t
298 AccelerantHWInterface::_SetupDefaultHooks()
299 {
300 	// required
301 	fAccAcquireEngine = (acquire_engine)fAccelerantHook(B_ACQUIRE_ENGINE, NULL);
302 	fAccReleaseEngine = (release_engine)fAccelerantHook(B_RELEASE_ENGINE, NULL);
303 	fAccSyncToToken = (sync_to_token)fAccelerantHook(B_SYNC_TO_TOKEN, NULL);
304 	fAccGetModeCount = (accelerant_mode_count)fAccelerantHook(B_ACCELERANT_MODE_COUNT, NULL);
305 	fAccGetModeList = (get_mode_list)fAccelerantHook(B_GET_MODE_LIST, NULL);
306 	fAccGetFrameBufferConfig = (get_frame_buffer_config)fAccelerantHook(B_GET_FRAME_BUFFER_CONFIG, NULL);
307 	fAccSetDisplayMode = (set_display_mode)fAccelerantHook(B_SET_DISPLAY_MODE, NULL);
308 	fAccGetDisplayMode = (get_display_mode)fAccelerantHook(B_GET_DISPLAY_MODE, NULL);
309 	fAccGetPixelClockLimits = (get_pixel_clock_limits)fAccelerantHook(B_GET_PIXEL_CLOCK_LIMITS, NULL);
310 
311 	if (!fAccAcquireEngine || !fAccReleaseEngine || !fAccGetFrameBufferConfig
312 		|| !fAccGetModeCount || !fAccGetModeList || !fAccSetDisplayMode
313 		|| !fAccGetDisplayMode || !fAccGetPixelClockLimits) {
314 		return B_ERROR;
315 	}
316 
317 	// optional
318 	fAccGetTimingConstraints = (get_timing_constraints)fAccelerantHook(B_GET_TIMING_CONSTRAINTS, NULL);
319 	fAccProposeDisplayMode = (propose_display_mode)fAccelerantHook(B_PROPOSE_DISPLAY_MODE, NULL);
320 
321 	// cursor
322 	fAccSetCursorShape = (set_cursor_shape)fAccelerantHook(B_SET_CURSOR_SHAPE, NULL);
323 	fAccMoveCursor = (move_cursor)fAccelerantHook(B_MOVE_CURSOR, NULL);
324 	fAccShowCursor = (show_cursor)fAccelerantHook(B_SHOW_CURSOR, NULL);
325 
326 	// dpms
327 //	fAccDPMSCapabilities = (dpms_capabilities)fAccelerantHook(B_DPMS_CAPABILITIES, NULL);
328 //	fAccDPMSMode = (dpms_mode)fAccelerantHook(B_DPMS_MODE, NULL);
329 //	fAccSetDPMSMode = (set_dpms_mode)fAccelerantHook(B_SET_DPMS_MODE, NULL);
330 
331 	// update acceleration hooks
332 	// TODO: would actually have to pass a valid display_mode!
333 	fAccFillRect = (fill_rectangle)fAccelerantHook(B_FILL_RECTANGLE, NULL);
334 	fAccInvertRect = (invert_rectangle)fAccelerantHook(B_INVERT_RECTANGLE, NULL);
335 	fAccScreenBlit = (screen_to_screen_blit)fAccelerantHook(B_SCREEN_TO_SCREEN_BLIT, NULL);
336 
337 	return B_OK;
338 }
339 
340 // Shutdown
341 status_t
342 AccelerantHWInterface::Shutdown()
343 {
344 	if (fAccelerantHook) {
345 		uninit_accelerant UninitAccelerant = (uninit_accelerant)fAccelerantHook(B_UNINIT_ACCELERANT, NULL);
346 		if (UninitAccelerant)
347 			UninitAccelerant();
348 	}
349 
350 	if (fAccelerantImage >= 0)
351 		unload_add_on(fAccelerantImage);
352 
353 	if (fCardFD >= 0)
354 		close(fCardFD);
355 
356 	return B_OK;
357 }
358 /*
359 // SetMode
360 status_t
361 AccelerantHWInterface::SetMode(const display_mode &mode)
362 {
363 	AutoWriteLocker _(this);
364 	// TODO: There are places this function can fail,
365 	// maybe it needs to roll back changes in case of an
366 	// error.
367 
368 	// prevent from doing the unnecessary
369 	if (fModeCount > 0 && fBackBuffer && fFrontBuffer
370 		&& fDisplayMode == mode) {
371 		// TODO: better comparison of display modes
372 		return B_OK;
373 	}
374 
375 	// just try to set the mode - we let the graphics driver
376 	// approve or deny the request, as it should know best
377 
378 	fDisplayMode = mode;
379 
380 	if (fAccSetDisplayMode(&fDisplayMode) != B_OK) {
381 		ATRACE(("setting display mode failed\n"));
382 		fAccGetDisplayMode(&fDisplayMode);
383 			// We just keep the current mode and continue.
384 			// Note, on startup, this may be different from
385 			// what we think is the current display mode
386 	}
387 
388 	// update frontbuffer
389 	fFrontBuffer->SetDisplayMode(fDisplayMode);
390 	if (_UpdateFrameBufferConfig() != B_OK)
391 		return B_ERROR;
392 
393 	// Update the frame buffer used by the on-screen KDL
394 #ifdef __HAIKU__
395 	uint32 depth = (fFrameBufferConfig.bytes_per_row / fDisplayMode.virtual_width) << 3;
396 	if (fDisplayMode.space == B_RGB15)
397 		depth = 15;
398 
399 	_kern_frame_buffer_update(fFrameBufferConfig.frame_buffer,
400 		fDisplayMode.virtual_width, fDisplayMode.virtual_height,
401 		depth, fFrameBufferConfig.bytes_per_row);
402 #endif
403 
404 	// update backbuffer if neccessary
405 	if (!fBackBuffer || fBackBuffer->Width() != fDisplayMode.virtual_width
406 		|| fBackBuffer->Height() != fDisplayMode.virtual_height) {
407 		// NOTE: backbuffer is always B_RGBA32, this simplifies the
408 		// drawing backend implementation tremendously for the time
409 		// being. The color space conversion is handled in CopyBackToFront()
410 
411 		delete fBackBuffer;
412 		fBackBuffer = NULL;
413 
414 		// TODO: Above not true anymore for single buffered mode!!!
415 		// -> fall back to double buffer for fDisplayMode.space != B_RGB32
416 		// as intermediate solution...
417 		bool doubleBuffered = HWInterface::IsDoubleBuffered();
418 		if ((color_space)fDisplayMode.space != B_RGB32 &&
419 			(color_space)fDisplayMode.space != B_RGBA32)
420 			doubleBuffered = true;
421 
422 		if (doubleBuffered) {
423 			fBackBuffer = new(nothrow) MallocBuffer(fDisplayMode.virtual_width,
424 													fDisplayMode.virtual_height);
425 
426 			status_t ret = fBackBuffer ? fBackBuffer->InitCheck() : B_NO_MEMORY;
427 			if (ret < B_OK) {
428 				delete fBackBuffer;
429 				fBackBuffer = NULL;
430 				return ret;
431 			}
432 			// clear out backbuffer, alpha is 255 this way
433 			memset(fBackBuffer->Bits(), 255, fBackBuffer->BitsLength());
434 		}
435 	}
436 
437 	// update acceleration hooks
438 	fAccFillRect = (fill_rectangle)fAccelerantHook(B_FILL_RECTANGLE, (void *)&fDisplayMode);
439 	fAccInvertRect = (invert_rectangle)fAccelerantHook(B_INVERT_RECTANGLE,
440 		(void *)&fDisplayMode);
441 	fAccScreenBlit = (screen_to_screen_blit)fAccelerantHook(B_SCREEN_TO_SCREEN_BLIT,
442 		(void *)&fDisplayMode);
443 
444 	return B_OK;
445 }
446 
447 
448 void
449 AccelerantHWInterface::GetMode(display_mode *mode)
450 {
451 	if (mode && ReadLock()) {
452 		*mode = fDisplayMode;
453 		ReadUnlock();
454 	}
455 }
456 
457 
458 status_t
459 AccelerantHWInterface::_UpdateModeList()
460 {
461 	fModeCount = fAccGetModeCount();
462 	if (fModeCount <= 0)
463 		return B_ERROR;
464 
465 	delete[] fModeList;
466 	fModeList = new(nothrow) display_mode[fModeCount];
467 	if (!fModeList)
468 		return B_NO_MEMORY;
469 
470 	if (fAccGetModeList(fModeList) != B_OK) {
471 		ATRACE(("unable to get mode list\n"));
472 		return B_ERROR;
473 	}
474 
475 	return B_OK;
476 }
477 
478 
479 status_t
480 AccelerantHWInterface::_UpdateFrameBufferConfig()
481 {
482 	if (fAccGetFrameBufferConfig(&fFrameBufferConfig) != B_OK) {
483 		ATRACE(("unable to get frame buffer config\n"));
484 		return B_ERROR;
485 	}
486 
487 	fFrontBuffer->SetFrameBufferConfig(fFrameBufferConfig);
488 	return B_OK;
489 }
490 
491 
492 status_t
493 AccelerantHWInterface::GetDeviceInfo(accelerant_device_info *info)
494 {
495 	get_accelerant_device_info GetAccelerantDeviceInfo = (get_accelerant_device_info)fAccelerantHook(B_GET_ACCELERANT_DEVICE_INFO, NULL);
496 	if (!GetAccelerantDeviceInfo) {
497 		ATRACE(("No B_GET_ACCELERANT_DEVICE_INFO hook found\n"));
498 		return B_UNSUPPORTED;
499 	}
500 
501 	return GetAccelerantDeviceInfo(info);
502 }
503 
504 
505 status_t
506 AccelerantHWInterface::GetFrameBufferConfig(frame_buffer_config& config)
507 {
508 	config = fFrameBufferConfig;
509 	return B_OK;
510 }
511 
512 
513 status_t
514 AccelerantHWInterface::GetModeList(display_mode** modes, uint32 *count)
515 {
516 	AutoReadLocker _(this);
517 
518 	if (!count || !modes)
519 		return B_BAD_VALUE;
520 
521 	status_t ret = fModeList ? B_OK : _UpdateModeList();
522 
523 	if (ret >= B_OK) {
524 		*modes = new(nothrow) display_mode[fModeCount];
525 		if (*modes) {
526 			*count = fModeCount;
527 			memcpy(*modes, fModeList, sizeof(display_mode) * fModeCount);
528 		} else {
529 			*count = 0;
530 			ret = B_NO_MEMORY;
531 		}
532 	}
533 	return ret;
534 }
535 
536 status_t
537 AccelerantHWInterface::GetPixelClockLimits(display_mode *mode, uint32 *low, uint32 *high)
538 {
539 	AutoReadLocker _(this);
540 
541 	if (!mode || !low || !high)
542 		return B_BAD_VALUE;
543 
544 	return fAccGetPixelClockLimits(mode, low, high);
545 }
546 
547 status_t
548 AccelerantHWInterface::GetTimingConstraints(display_timing_constraints *dtc)
549 {
550 	AutoReadLocker _(this);
551 
552 	if (!dtc)
553 		return B_BAD_VALUE;
554 
555 	if (fAccGetTimingConstraints)
556 		return fAccGetTimingConstraints(dtc);
557 
558 	return B_UNSUPPORTED;
559 }
560 
561 status_t
562 AccelerantHWInterface::ProposeMode(display_mode *candidate, const display_mode *low, const display_mode *high)
563 {
564 	AutoReadLocker _(this);
565 
566 	if (!candidate || !low || !high)
567 		return B_BAD_VALUE;
568 
569 	if (!fAccProposeDisplayMode)
570 		return B_UNSUPPORTED;
571 
572 	// avoid const issues
573 	display_mode this_high, this_low;
574 	this_high = *high;
575 	this_low = *low;
576 
577 	return fAccProposeDisplayMode(candidate, &this_low, &this_high);
578 }
579 
580 // RetraceSemaphore
581 sem_id
582 AccelerantHWInterface::RetraceSemaphore()
583 {
584 	accelerant_retrace_semaphore AccelerantRetraceSemaphore = (accelerant_retrace_semaphore)fAccelerantHook(B_ACCELERANT_RETRACE_SEMAPHORE, NULL);
585 	if (!AccelerantRetraceSemaphore)
586 		return B_UNSUPPORTED;
587 
588 	return AccelerantRetraceSemaphore();
589 }
590 
591 // WaitForRetrace
592 status_t
593 AccelerantHWInterface::WaitForRetrace(bigtime_t timeout)
594 {
595 	AutoReadLocker _(this);
596 
597 	accelerant_retrace_semaphore AccelerantRetraceSemaphore = (accelerant_retrace_semaphore)fAccelerantHook(B_ACCELERANT_RETRACE_SEMAPHORE, NULL);
598 	if (!AccelerantRetraceSemaphore)
599 		return B_UNSUPPORTED;
600 
601 	sem_id sem = AccelerantRetraceSemaphore();
602 	if (sem < 0)
603 		return B_ERROR;
604 
605 	return acquire_sem_etc(sem, 1, B_RELATIVE_TIMEOUT, timeout);
606 }
607 
608 // SetDPMSMode
609 status_t
610 AccelerantHWInterface::SetDPMSMode(const uint32 &state)
611 {
612 	AutoWriteLocker _(this);
613 
614 	if (!fAccSetDPMSMode)
615 		return B_UNSUPPORTED;
616 
617 	return fAccSetDPMSMode(state);
618 }
619 
620 // DPMSMode
621 uint32
622 AccelerantHWInterface::DPMSMode()
623 {
624 	AutoReadLocker _(this);
625 
626 	if (!fAccDPMSMode)
627 		return B_UNSUPPORTED;
628 
629 	return fAccDPMSMode();
630 }
631 
632 // DPMSCapabilities
633 uint32
634 AccelerantHWInterface::DPMSCapabilities()
635 {
636 	AutoReadLocker _(this);
637 
638 	if (!fAccDPMSCapabilities)
639 		return B_UNSUPPORTED;
640 
641 	return fAccDPMSCapabilities();
642 }
643 */
644 // AvailableHardwareAcceleration
645 uint32
646 AccelerantHWInterface::AvailableHWAcceleration() const
647 {
648 	uint32 flags = 0;
649 
650 /*	if (!IsDoubleBuffered()) {
651 		if (fAccScreenBlit)
652 			flags |= HW_ACC_COPY_REGION;
653 		if (fAccFillRect)
654 			flags |= HW_ACC_FILL_REGION;
655 		if (fAccInvertRect)
656 			flags |= HW_ACC_INVERT_REGION;
657 	}*/
658 
659 	return flags;
660 }
661 
662 // CopyRegion
663 void
664 AccelerantHWInterface::CopyRegion(const clipping_rect* sortedRectList,
665 								  uint32 count, int32 xOffset, int32 yOffset)
666 {
667 	if (fAccScreenBlit && fAccAcquireEngine) {
668 		if (fAccAcquireEngine(B_2D_ACCELERATION, 0xff, &fSyncToken, &fEngineToken) >= B_OK) {
669 
670 			// convert the rects
671 			blit_params* params = new blit_params[count];
672 			for (uint32 i = 0; i < count; i++) {
673 				params[i].src_left = (uint16)sortedRectList[i].left;
674 				params[i].src_top = (uint16)sortedRectList[i].top;
675 
676 				params[i].dest_left = (uint16)sortedRectList[i].left + xOffset;
677 				params[i].dest_top = (uint16)sortedRectList[i].top + yOffset;
678 
679 				// NOTE: width and height are expressed as distance, not pixel count!
680 				params[i].width = (uint16)(sortedRectList[i].right - sortedRectList[i].left);
681 				params[i].height = (uint16)(sortedRectList[i].bottom - sortedRectList[i].top);
682 			}
683 
684 			// go
685 			fAccScreenBlit(fEngineToken, params, count);
686 
687 			// done
688 			if (fAccReleaseEngine)
689 				fAccReleaseEngine(fEngineToken, &fSyncToken);
690 
691 			// sync
692 			if (fAccSyncToToken)
693 				fAccSyncToToken(&fSyncToken);
694 
695 			delete[] params;
696 		}
697 	}
698 }
699 
700 // FillRegion
701 void
702 AccelerantHWInterface::FillRegion(/*const*/ BRegion& region, const rgb_color& color)
703 {
704 	if (fAccFillRect && fAccAcquireEngine) {
705 		if (fAccAcquireEngine(B_2D_ACCELERATION, 0xff, &fSyncToken, &fEngineToken) >= B_OK) {
706 
707 			// convert the region
708 			uint32 count;
709 			fill_rect_params* fillParams;
710 			_RegionToRectParams(&region, &fillParams, &count);
711 
712 			// go
713 			fAccFillRect(fEngineToken, _NativeColor(color), fillParams, count);
714 
715 			// done
716 			if (fAccReleaseEngine)
717 				fAccReleaseEngine(fEngineToken, &fSyncToken);
718 
719 			// sync
720 			if (fAccSyncToToken)
721 				fAccSyncToToken(&fSyncToken);
722 
723 			delete[] fillParams;
724 		}
725 	}
726 }
727 
728 // InvertRegion
729 void
730 AccelerantHWInterface::InvertRegion(/*const*/ BRegion& region)
731 {
732 	if (fAccInvertRect && fAccAcquireEngine) {
733 		if (fAccAcquireEngine(B_2D_ACCELERATION, 0xff, &fSyncToken, &fEngineToken) >= B_OK) {
734 
735 			// convert the region
736 			uint32 count;
737 			fill_rect_params* fillParams;
738 			_RegionToRectParams(&region, &fillParams, &count);
739 
740 			// go
741 			fAccInvertRect(fEngineToken, fillParams, count);
742 
743 			// done
744 			if (fAccReleaseEngine)
745 				fAccReleaseEngine(fEngineToken, &fSyncToken);
746 
747 			// sync
748 			if (fAccSyncToToken)
749 				fAccSyncToToken(&fSyncToken);
750 
751 			delete[] fillParams;
752 		} else {
753 			fprintf(stderr, "AcquireEngine failed!\n");
754 		}
755 	} else {
756 		fprintf(stderr, "AccelerantHWInterface::InvertRegion() called, but hook not available!\n");
757 	}
758 }
759 /*
760 // SetCursor
761 void
762 AccelerantHWInterface::SetCursor(ServerCursor* cursor)
763 {
764 	HWInterface::SetCursor(cursor);
765 //	if (WriteLock()) {
766 		// TODO: implement setting the hard ware cursor
767 		// NOTE: cursor should be always B_RGBA32
768 		// NOTE: The HWInterface implementation should
769 		// still be called, since it takes ownership of
770 		// the cursor.
771 //		WriteUnlock();
772 //	}
773 }
774 
775 // SetCursorVisible
776 void
777 AccelerantHWInterface::SetCursorVisible(bool visible)
778 {
779 	HWInterface::SetCursorVisible(visible);
780 //	if (WriteLock()) {
781 		// TODO: update graphics hardware
782 //		WriteUnlock();
783 //	}
784 }
785 
786 // MoveCursorTo
787 void
788 AccelerantHWInterface::MoveCursorTo(const float& x, const float& y)
789 {
790 	HWInterface::MoveCursorTo(x, y);
791 //	if (WriteLock()) {
792 		// TODO: update graphics hardware
793 //		WriteUnlock();
794 //	}
795 }
796 
797 // FrontBuffer
798 RenderingBuffer *
799 AccelerantHWInterface::FrontBuffer() const
800 {
801 	if (!fModeList)
802 		return NULL;
803 
804 	return fFrontBuffer;
805 }
806 
807 // BackBuffer
808 RenderingBuffer *
809 AccelerantHWInterface::BackBuffer() const
810 {
811 	if (!fModeList)
812 		return NULL;
813 
814 	return fBackBuffer;
815 }
816 
817 // IsDoubleBuffered
818 bool
819 AccelerantHWInterface::IsDoubleBuffered() const
820 {
821 	if (fModeList)
822 		return fBackBuffer != NULL;
823 
824 	return HWInterface::IsDoubleBuffered();
825 }
826 
827 // _DrawCursor
828 void
829 AccelerantHWInterface::_DrawCursor(BRect area) const
830 {
831 	// use the default implementation for now,
832 	// until we have a hardware cursor
833 	HWInterface::_DrawCursor(area);
834 	// TODO: this would only be called, if we don't have
835 	// a hardware cursor for some reason
836 }
837 */
838 // _RegionToRectParams
839 void
840 AccelerantHWInterface::_RegionToRectParams(/*const*/ BRegion* region,
841 										   fill_rect_params** params,
842 										   uint32* count) const
843 {
844 	*count = region->CountRects();
845 	*params = new fill_rect_params[*count];
846 
847 	for (uint32 i = 0; i < *count; i++) {
848 		clipping_rect r = region->RectAtInt(i);
849 		(*params)[i].left = (uint16)r.left;
850 		(*params)[i].top = (uint16)r.top;
851 		(*params)[i].right = (uint16)r.right;
852 		(*params)[i].bottom = (uint16)r.bottom;
853 	}
854 }
855 
856 // _NativeColor
857 uint32
858 AccelerantHWInterface::_NativeColor(const rgb_color& c) const
859 {
860 	// NOTE: This functions looks somehow suspicios to me.
861 	// It assumes that all graphics cards have the same native endianess, no?
862 /*	switch (fDisplayMode.space) {
863 		case B_CMAP8:
864 		case B_GRAY8:
865 			return color.GetColor8();
866 
867 		case B_RGB15_BIG:
868 		case B_RGBA15_BIG:
869 		case B_RGB15_LITTLE:
870 		case B_RGBA15_LITTLE:
871 			return color.GetColor15();
872 
873 		case B_RGB16_BIG:
874 		case B_RGB16_LITTLE:
875 			return color.GetColor16();
876 
877 		case B_RGB32_BIG:
878 		case B_RGBA32_BIG:
879 		case B_RGB32_LITTLE:
880 		case B_RGBA32_LITTLE: {
881 			rgb_color c = color.GetColor32();
882 			uint32 native = (c.alpha << 24) |
883 							(c.red << 16) |
884 							(c.green << 8) |
885 							(c.blue);
886 			return native;
887 		}
888 	}
889 	return 0;*/
890 	uint32 native = (c.alpha << 24) | (c.red << 16) | (c.green << 8) | (c.blue);
891 	return native;
892 }
893