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
31using 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
43AccelerantHWInterface::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
94AccelerantHWInterface::~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*/
106status_t
107AccelerantHWInterface::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*/
142int
143AccelerantHWInterface::_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
190status_t
191AccelerantHWInterface::_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...
255sprintf((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
296status_t
297AccelerantHWInterface::_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
340status_t
341AccelerantHWInterface::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
359status_t
360AccelerantHWInterface::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
447void
448AccelerantHWInterface::GetMode(display_mode *mode)
449{
450	if (mode && ReadLock()) {
451		*mode = fDisplayMode;
452		ReadUnlock();
453	}
454}
455
456
457status_t
458AccelerantHWInterface::_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
478status_t
479AccelerantHWInterface::_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
491status_t
492AccelerantHWInterface::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
504status_t
505AccelerantHWInterface::GetFrameBufferConfig(frame_buffer_config& config)
506{
507	config = fFrameBufferConfig;
508	return B_OK;
509}
510
511
512status_t
513AccelerantHWInterface::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
535status_t
536AccelerantHWInterface::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
546status_t
547AccelerantHWInterface::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
560status_t
561AccelerantHWInterface::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
580sem_id
581AccelerantHWInterface::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
591status_t
592AccelerantHWInterface::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
608status_t
609AccelerantHWInterface::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
620uint32
621AccelerantHWInterface::DPMSMode()
622{
623	AutoReadLocker _(this);
624
625	if (!fAccDPMSMode)
626		return B_UNSUPPORTED;
627
628	return fAccDPMSMode();
629}
630
631// DPMSCapabilities
632uint32
633AccelerantHWInterface::DPMSCapabilities()
634{
635	AutoReadLocker _(this);
636
637	if (!fAccDPMSCapabilities)
638		return B_UNSUPPORTED;
639
640	return fAccDPMSCapabilities();
641}
642*/
643// AvailableHardwareAcceleration
644uint32
645AccelerantHWInterface::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
662void
663AccelerantHWInterface::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
700void
701AccelerantHWInterface::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
728void
729AccelerantHWInterface::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
760void
761AccelerantHWInterface::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
775void
776AccelerantHWInterface::SetCursorVisible(bool visible)
777{
778	HWInterface::SetCursorVisible(visible);
779//	if (WriteLock()) {
780		// TODO: update graphics hardware
781//		WriteUnlock();
782//	}
783}
784
785// MoveCursorTo
786void
787AccelerantHWInterface::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
797RenderingBuffer *
798AccelerantHWInterface::FrontBuffer() const
799{
800	if (!fModeList)
801		return NULL;
802
803	return fFrontBuffer;
804}
805
806// BackBuffer
807RenderingBuffer *
808AccelerantHWInterface::BackBuffer() const
809{
810	if (!fModeList)
811		return NULL;
812
813	return fBackBuffer;
814}
815
816// IsDoubleBuffered
817bool
818AccelerantHWInterface::IsDoubleBuffered() const
819{
820	if (fModeList)
821		return fBackBuffer != NULL;
822
823	return HWInterface::IsDoubleBuffered();
824}
825
826// _DrawCursor
827void
828AccelerantHWInterface::_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
838void
839AccelerantHWInterface::_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
856uint32
857AccelerantHWInterface::_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