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