vfs: check userland buffers before reading them.
[haiku.git] / src / servers / app / drawing / DWindowHWInterface.cpp
blobe590ebbf96c2eb24598529152804c53cde3b48c2
1 /*
2 * Copyright 2001-2009, Haiku.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * DarkWyrm <bpmagic@columbus.rr.com>
7 * Michael Lotz <mmlr@mlotz.ch>
8 * Stephan Aßmus <superstippi@gmx.de>
9 */
12 /*! BView/BDirectWindow/Accelerant combination HWInterface implementation
16 #include "DWindowHWInterface.h"
18 #include <malloc.h>
19 #include <new>
20 #include <stdio.h>
22 #include <Application.h>
23 #include <Bitmap.h>
24 #include <Cursor.h>
25 #include <DirectWindow.h>
26 #include <Locker.h>
27 #include <Message.h>
28 #include <MessageFilter.h>
29 #include <MessageRunner.h>
30 #include <Region.h>
31 #include <Screen.h>
32 #include <String.h>
33 #include <View.h>
35 #include <Accelerant.h>
36 #include <graphic_driver.h>
37 #include <FindDirectory.h>
38 #include <image.h>
39 #include <dirent.h>
40 #include <sys/ioctl.h>
41 #include <unistd.h>
43 #include <ServerProtocol.h>
45 #include "DWindowBuffer.h"
46 #include "PortLink.h"
47 #include "RGBColor.h"
48 #include "ServerConfig.h"
49 #include "ServerCursor.h"
50 #include "UpdateQueue.h"
53 #ifdef DEBUG_DRIVER_MODULE
54 # include <stdio.h>
55 # define STRACE(x) printf x
56 #else
57 # define STRACE(x) ;
58 #endif
61 const unsigned char kEmptyCursor[] = { 16, 1, 0, 0,
62 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
63 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
64 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
65 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
68 static int32
69 run_app_thread(void* cookie)
71 if (BApplication* app = (BApplication*)cookie) {
72 app->Lock();
73 app->Run();
75 return 0;
79 //#define INPUTSERVER_TEST_MODE 1
82 class DView : public BView {
83 public:
84 DView(BRect bounds);
85 virtual ~DView();
87 // DView
88 void ForwardMessage(BMessage* message = NULL);
90 private:
91 port_id fInputPort;
94 class DWindow : public BWindow {
95 public:
96 DWindow(BRect frame,
97 DWindowHWInterface* interface,
98 DWindowBuffer* buffer);
99 virtual ~DWindow();
101 virtual bool QuitRequested();
103 // virtual void DirectConnected(direct_buffer_info* info);
105 virtual void FrameMoved(BPoint newOffset);
107 private:
108 DWindowHWInterface* fHWInterface;
109 DWindowBuffer* fBuffer;
112 class DirectMessageFilter : public BMessageFilter {
113 public:
114 DirectMessageFilter(DView* view);
116 virtual filter_result Filter(BMessage *message, BHandler** _target);
118 private:
119 DView* fView;
123 // #pragma mark -
126 DView::DView(BRect bounds)
128 BView(bounds, "graphics card view", B_FOLLOW_ALL, 0)
130 SetViewColor(B_TRANSPARENT_COLOR);
131 #ifndef INPUTSERVER_TEST_MODE
132 fInputPort = create_port(200, SERVER_INPUT_PORT);
133 #else
134 fInputPort = create_port(100, "ViewInputDevice");
135 #endif
137 #ifdef ENABLE_INPUT_SERVER_EMULATION
138 AddFilter(new DirectMessageFilter(this));
139 #endif
143 DView::~DView()
148 /*! This function emulates the Input Server by sending the *exact* same kind of
149 messages to the server's port. Being we're using a regular window, it would
150 make little sense to do anything else.
152 void
153 DView::ForwardMessage(BMessage* message)
155 if (message == NULL)
156 message = Window()->CurrentMessage();
157 if (message == NULL)
158 return;
160 // remove some fields that potentially mess up our own message processing
161 BMessage copy = *message;
162 copy.RemoveName("screen_where");
163 copy.RemoveName("be:transit");
164 copy.RemoveName("be:view_where");
165 copy.RemoveName("be:cursor_needed");
167 size_t length = copy.FlattenedSize();
168 char stream[length];
170 if (copy.Flatten(stream, length) == B_OK)
171 write_port(fInputPort, 0, stream, length);
175 // #pragma mark -
178 DirectMessageFilter::DirectMessageFilter(DView* view)
180 BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE),
181 fView(view)
186 filter_result
187 DirectMessageFilter::Filter(BMessage* message, BHandler** target)
189 switch (message->what) {
190 case B_KEY_DOWN:
191 case B_UNMAPPED_KEY_DOWN:
192 case B_KEY_UP:
193 case B_UNMAPPED_KEY_UP:
194 case B_MOUSE_DOWN:
195 case B_MOUSE_UP:
196 case B_MOUSE_WHEEL_CHANGED:
197 fView->ForwardMessage(message);
198 return B_SKIP_MESSAGE;
200 case B_MOUSE_MOVED:
202 int32 transit;
203 if (message->FindInt32("be:transit", &transit) == B_OK
204 && transit == B_ENTERED_VIEW) {
205 // A bug in R5 prevents this call from having an effect if
206 // called elsewhere, and calling it here works, if we're lucky :-)
207 BCursor cursor(kEmptyCursor);
208 fView->SetViewCursor(&cursor, true);
210 fView->ForwardMessage(message);
211 return B_SKIP_MESSAGE;
215 return B_DISPATCH_MESSAGE;
219 // #pragma mark -
222 DWindow::DWindow(BRect frame, DWindowHWInterface* interface,
223 DWindowBuffer* buffer)
225 BWindow(frame, "Haiku App Server", B_TITLED_WINDOW_LOOK,
226 B_NORMAL_WINDOW_FEEL,
227 B_NOT_ZOOMABLE | B_NOT_RESIZABLE | B_NOT_MOVABLE),
228 fHWInterface(interface),
229 fBuffer(buffer)
231 DView* view = new DView(Bounds());
232 AddChild(view);
233 view->MakeFocus();
234 // make it receive key events
238 DWindow::~DWindow()
243 bool
244 DWindow::QuitRequested()
246 port_id serverport = find_port(SERVER_PORT_NAME);
248 if (serverport >= 0) {
249 BPrivate::PortLink link(serverport);
250 link.StartMessage(B_QUIT_REQUESTED);
251 link.Flush();
252 } else
253 printf("ERROR: couldn't find the app_server's main port!");
255 // we don't quit on ourself, we let us be Quit()!
256 return false;
261 void
262 DWindow::DirectConnected(direct_buffer_info* info)
264 // fDesktop->LockClipping();
266 // fEngine.Lock();
268 switch(info->buffer_state & B_DIRECT_MODE_MASK) {
269 case B_DIRECT_START:
270 case B_DIRECT_MODIFY:
271 fBuffer->SetTo(info);
272 // fDesktop->SetOffset(info->window_bounds.left, info->window_bounds.top);
273 break;
274 case B_DIRECT_STOP:
275 fBuffer->SetTo(NULL);
276 break;
279 // fDesktop->SetMasterClipping(&fBuffer.WindowClipping());
281 // fEngine.Unlock();
283 // fDesktop->UnlockClipping();
288 void
289 DWindow::FrameMoved(BPoint newOffset)
291 fHWInterface->SetOffset((int32)newOffset.x, (int32)newOffset.y);
295 // #pragma mark -
298 const int32 kDefaultParamsCount = 64;
300 DWindowHWInterface::DWindowHWInterface()
302 HWInterface(),
303 fFrontBuffer(new DWindowBuffer()),
304 fWindow(NULL),
306 fXOffset(50),
307 fYOffset(50),
309 fCardFD(-1),
310 fAccelerantImage(-1),
311 fAccelerantHook(NULL),
312 fEngineToken(NULL),
313 fSyncToken(),
315 // required hooks
316 fAccAcquireEngine(NULL),
317 fAccReleaseEngine(NULL),
318 fAccSyncToToken(NULL),
319 fAccGetModeCount(NULL),
320 fAccGetModeList(NULL),
321 fAccGetFrameBufferConfig(NULL),
322 fAccSetDisplayMode(NULL),
323 fAccGetDisplayMode(NULL),
324 fAccGetPixelClockLimits(NULL),
326 // optional accelerant hooks
327 fAccGetTimingConstraints(NULL),
328 fAccProposeDisplayMode(NULL),
329 fAccFillRect(NULL),
330 fAccInvertRect(NULL),
331 fAccScreenBlit(NULL),
332 fAccSetCursorShape(NULL),
333 fAccMoveCursor(NULL),
334 fAccShowCursor(NULL),
336 fRectParams(new (std::nothrow) fill_rect_params[kDefaultParamsCount]),
337 fRectParamsCount(kDefaultParamsCount),
338 fBlitParams(new (std::nothrow) blit_params[kDefaultParamsCount]),
339 fBlitParamsCount(kDefaultParamsCount)
341 fDisplayMode.virtual_width = 800;
342 fDisplayMode.virtual_height = 600;
343 fDisplayMode.space = B_RGBA32;
345 memset(&fSyncToken, 0, sizeof(sync_token));
349 DWindowHWInterface::~DWindowHWInterface()
351 if (fWindow) {
352 fWindow->Lock();
353 fWindow->Quit();
356 delete[] fRectParams;
357 delete[] fBlitParams;
359 delete fFrontBuffer;
361 be_app->Lock();
362 be_app->Quit();
363 delete be_app;
367 status_t
368 DWindowHWInterface::Initialize()
370 status_t ret = HWInterface::Initialize();
372 if (!fRectParams || !fBlitParams)
373 return B_NO_MEMORY;
375 if (ret >= B_OK) {
376 for (int32 i = 1; fCardFD != B_ENTRY_NOT_FOUND; i++) {
377 fCardFD = _OpenGraphicsDevice(i);
378 if (fCardFD < 0) {
379 STRACE(("Failed to open graphics device\n"));
380 continue;
383 if (_OpenAccelerant(fCardFD) == B_OK)
384 break;
386 close(fCardFD);
387 // _OpenAccelerant() failed, try to open next graphics card
390 return fCardFD >= 0 ? B_OK : fCardFD;
392 return ret;
396 /*! \brief Opens a graphics device for read-write access
397 \param deviceNumber Number identifying which graphics card to open (1 for
398 first card)
399 \return The file descriptor for the opened graphics device
401 The deviceNumber is relative to the number of graphics devices that can be
402 successfully opened. One represents the first card that can be successfully
403 opened (not necessarily the first one listed in the directory).
404 Graphics drivers must be able to be opened more than once, so we really get
405 the first working entry.
408 DWindowHWInterface::_OpenGraphicsDevice(int deviceNumber)
410 DIR *directory = opendir("/dev/graphics");
411 if (!directory)
412 return -1;
414 // ToDo: the former R5 "stub" driver is called "vesa" under Haiku; however,
415 // we do not need to avoid this driver this way when is has been ported
416 // to the new driver architecture - the special case here can then be
417 // removed.
418 int count = 0;
419 struct dirent *entry = NULL;
420 int current_card_fd = -1;
421 char path[PATH_MAX];
422 while (count < deviceNumber && (entry = readdir(directory)) != NULL) {
423 if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..") ||
424 !strcmp(entry->d_name, "stub") || !strcmp(entry->d_name, "vesa"))
425 continue;
427 if (current_card_fd >= 0) {
428 close(current_card_fd);
429 current_card_fd = -1;
432 sprintf(path, "/dev/graphics/%s", entry->d_name);
433 current_card_fd = open(path, B_READ_WRITE);
434 if (current_card_fd >= 0)
435 count++;
438 // Open VESA driver if we were not able to get a better one
439 if (count < deviceNumber) {
440 if (deviceNumber == 1) {
441 sprintf(path, "/dev/graphics/vesa");
442 current_card_fd = open(path, B_READ_WRITE);
443 } else {
444 close(current_card_fd);
445 current_card_fd = B_ENTRY_NOT_FOUND;
449 if (entry)
450 fCardNameInDevFS = entry->d_name;
452 return current_card_fd;
456 status_t
457 DWindowHWInterface::_OpenAccelerant(int device)
459 char signature[1024];
460 if (ioctl(device, B_GET_ACCELERANT_SIGNATURE,
461 &signature, sizeof(signature)) != B_OK)
462 return B_ERROR;
464 STRACE(("accelerant signature is: %s\n", signature));
466 struct stat accelerant_stat;
467 const static directory_which dirs[] = {
468 B_USER_NONPACKAGED_ADDONS_DIRECTORY,
469 B_USER_ADDONS_DIRECTORY,
470 B_SYSTEM_NONPACKAGED_ADDONS_DIRECTORY,
471 B_SYSTEM_ADDONS_DIRECTORY
474 fAccelerantImage = -1;
476 for (uint32 i = 0; i < sizeof(dirs) / sizeof(directory_which); i++) {
477 char path[PATH_MAX];
478 if (find_directory(dirs[i], -1, false, path, PATH_MAX) != B_OK)
479 continue;
481 strcat(path, "/accelerants/");
482 strcat(path, signature);
483 if (stat(path, &accelerant_stat) != 0)
484 continue;
486 fAccelerantImage = load_add_on(path);
487 if (fAccelerantImage >= 0) {
488 if (get_image_symbol(fAccelerantImage, B_ACCELERANT_ENTRY_POINT,
489 B_SYMBOL_TYPE_ANY, (void**)(&fAccelerantHook)) != B_OK ) {
490 STRACE(("unable to get B_ACCELERANT_ENTRY_POINT\n"));
491 unload_add_on(fAccelerantImage);
492 fAccelerantImage = -1;
493 return B_ERROR;
497 accelerant_clone_info_size cloneInfoSize;
498 cloneInfoSize = (accelerant_clone_info_size)fAccelerantHook(
499 B_ACCELERANT_CLONE_INFO_SIZE, NULL);
500 if (!cloneInfoSize) {
501 STRACE(("unable to get B_ACCELERANT_CLONE_INFO_SIZE (%s)\n", path));
502 unload_add_on(fAccelerantImage);
503 fAccelerantImage = -1;
504 return B_ERROR;
507 ssize_t cloneSize = cloneInfoSize();
508 void* cloneInfoData = malloc(cloneSize);
510 // get_accelerant_clone_info getCloneInfo;
511 // getCloneInfo = (get_accelerant_clone_info)fAccelerantHook(B_GET_ACCELERANT_CLONE_INFO, NULL);
512 // if (!getCloneInfo) {
513 // STRACE(("unable to get B_GET_ACCELERANT_CLONE_INFO (%s)\n", path));
514 // unload_add_on(fAccelerantImage);
515 // fAccelerantImage = -1;
516 // return B_ERROR;
517 // }
518 // printf("getCloneInfo: %p\n", getCloneInfo);
520 // getCloneInfo(cloneInfoData);
521 // TODO: this is what works for the ATI Radeon driver...
522 sprintf((char*)cloneInfoData, "graphics/%s", fCardNameInDevFS.String());
524 clone_accelerant cloneAccelerant;
525 cloneAccelerant = (clone_accelerant)fAccelerantHook(B_CLONE_ACCELERANT, NULL);
526 if (!cloneAccelerant) {
527 STRACE(("unable to get B_CLONE_ACCELERANT\n"));
528 unload_add_on(fAccelerantImage);
529 fAccelerantImage = -1;
530 free(cloneInfoData);
531 return B_ERROR;
533 status_t ret = cloneAccelerant(cloneInfoData);
534 if (ret != B_OK) {
535 STRACE(("Cloning accelerant unsuccessful: %s\n", strerror(ret)));
536 unload_add_on(fAccelerantImage);
537 fAccelerantImage = -1;
538 return B_ERROR;
541 break;
545 if (fAccelerantImage < B_OK)
546 return B_ERROR;
548 if (_SetupDefaultHooks() != B_OK) {
549 STRACE(("cannot setup default hooks\n"));
551 uninit_accelerant uninitAccelerant = (uninit_accelerant)
552 fAccelerantHook(B_UNINIT_ACCELERANT, NULL);
553 if (uninitAccelerant != NULL)
554 uninitAccelerant();
556 unload_add_on(fAccelerantImage);
557 return B_ERROR;
558 } else {
559 _UpdateFrameBufferConfig();
562 return B_OK;
566 status_t
567 DWindowHWInterface::_SetupDefaultHooks()
569 // required
570 fAccAcquireEngine = (acquire_engine)fAccelerantHook(B_ACQUIRE_ENGINE, NULL);
571 fAccReleaseEngine = (release_engine)fAccelerantHook(B_RELEASE_ENGINE, NULL);
572 fAccSyncToToken = (sync_to_token)fAccelerantHook(B_SYNC_TO_TOKEN, NULL);
573 fAccGetModeCount = (accelerant_mode_count)fAccelerantHook(
574 B_ACCELERANT_MODE_COUNT, NULL);
575 fAccGetModeList = (get_mode_list)fAccelerantHook(B_GET_MODE_LIST, NULL);
576 fAccGetFrameBufferConfig = (get_frame_buffer_config)fAccelerantHook(
577 B_GET_FRAME_BUFFER_CONFIG, NULL);
578 fAccSetDisplayMode = (set_display_mode)fAccelerantHook(
579 B_SET_DISPLAY_MODE, NULL);
580 fAccGetDisplayMode = (get_display_mode)fAccelerantHook(
581 B_GET_DISPLAY_MODE, NULL);
582 fAccGetPixelClockLimits = (get_pixel_clock_limits)fAccelerantHook(
583 B_GET_PIXEL_CLOCK_LIMITS, NULL);
585 if (!fAccAcquireEngine || !fAccReleaseEngine || !fAccGetFrameBufferConfig
586 || !fAccGetModeCount || !fAccGetModeList || !fAccSetDisplayMode
587 || !fAccGetDisplayMode || !fAccGetPixelClockLimits) {
588 return B_ERROR;
591 // optional
592 fAccGetTimingConstraints = (get_timing_constraints)fAccelerantHook(
593 B_GET_TIMING_CONSTRAINTS, NULL);
594 fAccProposeDisplayMode = (propose_display_mode)fAccelerantHook(
595 B_PROPOSE_DISPLAY_MODE, NULL);
597 // cursor
598 fAccSetCursorShape = (set_cursor_shape)fAccelerantHook(
599 B_SET_CURSOR_SHAPE, NULL);
600 fAccMoveCursor = (move_cursor)fAccelerantHook(B_MOVE_CURSOR, NULL);
601 fAccShowCursor = (show_cursor)fAccelerantHook(B_SHOW_CURSOR, NULL);
603 // update acceleration hooks
604 // TODO: would actually have to pass a valid display_mode!
605 fAccFillRect = (fill_rectangle)fAccelerantHook(B_FILL_RECTANGLE, NULL);
606 fAccInvertRect = (invert_rectangle)fAccelerantHook(B_INVERT_RECTANGLE, NULL);
607 fAccScreenBlit = (screen_to_screen_blit)fAccelerantHook(
608 B_SCREEN_TO_SCREEN_BLIT, NULL);
610 return B_OK;
614 status_t
615 DWindowHWInterface::_UpdateFrameBufferConfig()
617 frame_buffer_config config;
618 if (fAccGetFrameBufferConfig(&config) != B_OK) {
619 STRACE(("unable to get frame buffer config\n"));
620 return B_ERROR;
623 fFrontBuffer->SetTo(&config, fXOffset, fYOffset, fDisplayMode.virtual_width,
624 fDisplayMode.virtual_height, (color_space)fDisplayMode.space);
626 return B_OK;
630 status_t
631 DWindowHWInterface::Shutdown()
633 printf("DWindowHWInterface::Shutdown()\n");
634 if (fAccelerantHook) {
635 uninit_accelerant UninitAccelerant
636 = (uninit_accelerant)fAccelerantHook(B_UNINIT_ACCELERANT, NULL);
637 if (UninitAccelerant)
638 UninitAccelerant();
641 if (fAccelerantImage >= 0)
642 unload_add_on(fAccelerantImage);
644 if (fCardFD >= 0)
645 close(fCardFD);
647 return B_OK;
651 status_t
652 DWindowHWInterface::SetMode(const display_mode& mode)
654 AutoWriteLocker _(this);
656 status_t ret = B_OK;
657 // prevent from doing the unnecessary
658 if (fFrontBuffer
659 && fDisplayMode.virtual_width == mode.virtual_width
660 && fDisplayMode.virtual_height == mode.virtual_height
661 && fDisplayMode.space == mode.space)
662 return ret;
664 // check if we support the mode
666 display_mode *modes;
667 uint32 modeCount, i;
668 if (GetModeList(&modes, &modeCount) != B_OK)
669 return B_NO_MEMORY;
671 for (i = 0; i < modeCount; i++) {
672 // we only care for the bare minimum
673 if (modes[i].virtual_width == mode.virtual_width
674 && modes[i].virtual_height == mode.virtual_height
675 && modes[i].space == mode.space) {
676 // take over settings
677 fDisplayMode = modes[i];
678 break;
682 delete[] modes;
684 if (i == modeCount)
685 return B_BAD_VALUE;
687 BRect frame(0.0, 0.0,
688 fDisplayMode.virtual_width - 1,
689 fDisplayMode.virtual_height - 1);
691 // create the window if we don't have one already
692 if (!fWindow) {
693 // if the window has not been created yet, the BApplication
694 // has not been created either, but we need one to display
695 // a real BWindow in the test environment.
696 // be_app->Run() needs to be called in another thread
697 BApplication* app = new BApplication(
698 "application/x-vnd.Haiku-test-app_server");
699 app->Unlock();
701 thread_id appThread = spawn_thread(run_app_thread, "app thread",
702 B_NORMAL_PRIORITY, app);
703 if (appThread >= B_OK)
704 ret = resume_thread(appThread);
705 else
706 ret = appThread;
708 if (ret < B_OK)
709 return ret;
711 fWindow = new DWindow(frame.OffsetByCopy(fXOffset, fYOffset), this,
712 fFrontBuffer);
714 // fire up the window thread but don't show it on screen yet
715 fWindow->Hide();
716 fWindow->Show();
719 if (fWindow->Lock()) {
720 // free and reallocate the bitmaps while the window is locked,
721 // so that the view does not accidentally draw a freed bitmap
723 if (ret >= B_OK) {
724 // change the window size and update the bitmap used for drawing
725 fWindow->ResizeTo(frame.Width(), frame.Height());
728 // window is hidden when this function is called the first time
729 if (fWindow->IsHidden())
730 fWindow->Show();
732 fWindow->Unlock();
733 } else {
734 ret = B_ERROR;
737 _UpdateFrameBufferConfig();
738 _NotifyFrameBufferChanged();
740 return ret;
744 void
745 DWindowHWInterface::GetMode(display_mode* mode)
747 if (mode && ReadLock()) {
748 *mode = fDisplayMode;
749 ReadUnlock();
754 status_t
755 DWindowHWInterface::GetDeviceInfo(accelerant_device_info* info)
757 // We really don't have to provide anything here because this is strictly
758 // a software-only driver, but we'll have some fun, anyway.
759 if (ReadLock()) {
760 info->version = 100;
761 sprintf(info->name, "Haiku, Inc. DWindowHWInterface");
762 sprintf(info->chipset, "Haiku, Inc. Chipset");
763 sprintf(info->serial_no, "3.14159265358979323846");
764 info->memory = 134217728; // 128 MB, not that we really have that much. :)
765 info->dac_speed = 0xFFFFFFFF; // *heh*
767 ReadUnlock();
770 return B_OK;
774 status_t
775 DWindowHWInterface::GetFrameBufferConfig(frame_buffer_config& config)
777 if (fFrontBuffer == NULL)
778 return B_ERROR;
780 config.frame_buffer = fFrontBuffer->Bits();
781 config.frame_buffer_dma = NULL;
782 config.bytes_per_row = fFrontBuffer->BytesPerRow();
784 return B_OK;
788 status_t
789 DWindowHWInterface::GetModeList(display_mode** _modes, uint32* _count)
791 AutoReadLocker _(this);
793 #if 1
794 // setup a whole bunch of different modes
795 const struct resolution { int32 width, height; } resolutions[] = {
796 {640, 480}, {800, 600}, {1024, 768}, {1152, 864}, {1280, 960},
797 {1280, 1024}, {1400, 1050}, {1600, 1200}
799 uint32 resolutionCount = sizeof(resolutions) / sizeof(resolutions[0]);
800 // const uint32 colors[] = {B_CMAP8, B_RGB15, B_RGB16, B_RGB32};
801 uint32 count = resolutionCount/* * 4*/;
803 display_mode* modes = new(std::nothrow) display_mode[count];
804 if (modes == NULL)
805 return B_NO_MEMORY;
807 *_modes = modes;
808 *_count = count;
810 int32 index = 0;
811 for (uint32 i = 0; i < resolutionCount; i++) {
812 modes[index].virtual_width = resolutions[i].width;
813 modes[index].virtual_height = resolutions[i].height;
814 modes[index].space = B_RGB32;
816 modes[index].h_display_start = 0;
817 modes[index].v_display_start = 0;
818 modes[index].timing.h_display = resolutions[i].width;
819 modes[index].timing.v_display = resolutions[i].height;
820 modes[index].timing.h_total = 22000;
821 modes[index].timing.v_total = 22000;
822 modes[index].timing.pixel_clock = ((uint32)modes[index].timing.h_total
823 * modes[index].timing.v_total * 60) / 1000;
824 modes[index].flags = B_PARALLEL_ACCESS;
826 index++;
828 #else
829 // support only a single mode, useful
830 // for testing a specific mode
831 display_mode *modes = new(std::nothrow) display_mode[1];
832 modes[0].virtual_width = 800;
833 modes[0].virtual_height = 600;
834 modes[0].space = B_BRGB32;
836 *_modes = modes;
837 *_count = 1;
838 #endif
840 return B_OK;
844 status_t
845 DWindowHWInterface::GetPixelClockLimits(display_mode* mode, uint32* low,
846 uint32* high)
848 return B_ERROR;
852 status_t
853 DWindowHWInterface::GetTimingConstraints(
854 display_timing_constraints* constraints)
856 return B_ERROR;
860 status_t
861 DWindowHWInterface::ProposeMode(display_mode* candidate,
862 const display_mode* low, const display_mode* high)
864 // We should be able to get away with this because we're not dealing with
865 // any specific hardware. This is a Good Thing(TM) because we can support
866 // any hardware we wish within reasonable expectaions and programmer
867 // laziness. :P
868 return B_OK;
872 sem_id
873 DWindowHWInterface::RetraceSemaphore()
875 return -1;
879 status_t
880 DWindowHWInterface::WaitForRetrace(bigtime_t timeout)
882 // Locking shouldn't be necessary here - R5 should handle this for us. :)
883 BScreen screen;
884 return screen.WaitForRetrace(timeout);
888 status_t
889 DWindowHWInterface::SetDPMSMode(uint32 state)
891 AutoWriteLocker _(this);
893 return BScreen().SetDPMS(state);
897 uint32
898 DWindowHWInterface::DPMSMode()
900 AutoReadLocker _(this);
902 return BScreen().DPMSState();
906 uint32
907 DWindowHWInterface::DPMSCapabilities()
909 AutoReadLocker _(this);
911 return BScreen().DPMSCapabilites();
915 status_t
916 DWindowHWInterface::SetBrightness(float brightness)
918 AutoReadLocker _(this);
920 return BScreen().SetBrightness(brightness);
924 status_t
925 DWindowHWInterface::GetBrightness(float* brightness)
927 AutoReadLocker _(this);
929 return BScreen().GetBrightness(brightness);
933 uint32
934 DWindowHWInterface::AvailableHWAcceleration() const
936 uint32 flags = 0;
938 if (!IsDoubleBuffered()) {
939 if (fAccScreenBlit)
940 flags |= HW_ACC_COPY_REGION;
941 if (fAccFillRect)
942 flags |= HW_ACC_FILL_REGION;
943 if (fAccInvertRect)
944 flags |= HW_ACC_INVERT_REGION;
947 return flags;
951 void
952 DWindowHWInterface::CopyRegion(const clipping_rect* sortedRectList,
953 uint32 count, int32 xOffset, int32 yOffset)
955 if (fAccScreenBlit && fAccAcquireEngine) {
956 if (fAccAcquireEngine(B_2D_ACCELERATION, 0xff, &fSyncToken,
957 &fEngineToken) >= B_OK) {
958 // make sure the blit_params cache is large enough
959 if (fBlitParamsCount < count) {
960 fBlitParamsCount = (count / kDefaultParamsCount + 1)
961 * kDefaultParamsCount;
962 // NOTE: realloc() could be used instead...
963 blit_params* params
964 = new(std::nothrow) blit_params[fBlitParamsCount];
965 if (params) {
966 delete[] fBlitParams;
967 fBlitParams = params;
968 } else {
969 count = fBlitParamsCount;
972 // convert the rects
973 for (uint32 i = 0; i < count; i++) {
974 fBlitParams[i].src_left
975 = (uint16)sortedRectList[i].left + fXOffset;
976 fBlitParams[i].src_top
977 = (uint16)sortedRectList[i].top + fYOffset;
979 fBlitParams[i].dest_left
980 = (uint16)sortedRectList[i].left + xOffset + fXOffset;
981 fBlitParams[i].dest_top
982 = (uint16)sortedRectList[i].top + yOffset + fYOffset;
984 // NOTE: width and height are expressed as distance, not count!
985 fBlitParams[i].width = (uint16)(sortedRectList[i].right
986 - sortedRectList[i].left);
987 fBlitParams[i].height = (uint16)(sortedRectList[i].bottom
988 - sortedRectList[i].top);
991 // go
992 fAccScreenBlit(fEngineToken, fBlitParams, count);
994 // done
995 if (fAccReleaseEngine)
996 fAccReleaseEngine(fEngineToken, &fSyncToken);
998 // sync
999 if (fAccSyncToToken)
1000 fAccSyncToToken(&fSyncToken);
1006 void
1007 DWindowHWInterface::FillRegion(/*const*/ BRegion& region,
1008 const rgb_color& color, bool autoSync)
1010 if (fAccFillRect && fAccAcquireEngine) {
1011 if (fAccAcquireEngine(B_2D_ACCELERATION, 0xff, &fSyncToken,
1012 &fEngineToken) >= B_OK) {
1013 // convert the region
1014 uint32 count;
1015 _RegionToRectParams(&region, &count);
1017 // go
1018 fAccFillRect(fEngineToken, _NativeColor(color), fRectParams, count);
1020 // done
1021 if (fAccReleaseEngine)
1022 fAccReleaseEngine(fEngineToken, &fSyncToken);
1024 // sync
1025 if (autoSync && fAccSyncToToken)
1026 fAccSyncToToken(&fSyncToken);
1032 void
1033 DWindowHWInterface::InvertRegion(/*const*/ BRegion& region)
1035 if (fAccInvertRect && fAccAcquireEngine) {
1036 if (fAccAcquireEngine(B_2D_ACCELERATION, 0xff, &fSyncToken,
1037 &fEngineToken) >= B_OK) {
1038 // convert the region
1039 uint32 count;
1040 _RegionToRectParams(&region, &count);
1042 // go
1043 fAccInvertRect(fEngineToken, fRectParams, count);
1045 // done
1046 if (fAccReleaseEngine)
1047 fAccReleaseEngine(fEngineToken, &fSyncToken);
1049 // sync
1050 if (fAccSyncToToken)
1051 fAccSyncToToken(&fSyncToken);
1053 } else {
1054 fprintf(stderr, "AcquireEngine failed!\n");
1056 } else {
1057 fprintf(stderr, "AccelerantHWInterface::InvertRegion() called, but "
1058 "hook not available!\n");
1063 void
1064 DWindowHWInterface::Sync()
1066 if (fAccSyncToToken)
1067 fAccSyncToToken(&fSyncToken);
1071 RenderingBuffer*
1072 DWindowHWInterface::FrontBuffer() const
1074 return fFrontBuffer;
1078 RenderingBuffer*
1079 DWindowHWInterface::BackBuffer() const
1081 return fFrontBuffer;
1085 bool
1086 DWindowHWInterface::IsDoubleBuffered() const
1088 return false;
1092 status_t
1093 DWindowHWInterface::Invalidate(const BRect& frame)
1095 return HWInterface::Invalidate(frame);
1099 void
1100 DWindowHWInterface::SetOffset(int32 left, int32 top)
1102 if (!WriteLock())
1103 return;
1105 fXOffset = left;
1106 fYOffset = top;
1108 _UpdateFrameBufferConfig();
1110 // TODO: someone would have to call DrawingEngine::Update() now!
1112 WriteUnlock();
1116 void
1117 DWindowHWInterface::_RegionToRectParams(/*const*/ BRegion* region,
1118 uint32* count) const
1120 *count = region->CountRects();
1121 if (fRectParamsCount < *count) {
1122 fRectParamsCount = (*count / kDefaultParamsCount + 1)
1123 * kDefaultParamsCount;
1124 // NOTE: realloc() could be used instead...
1125 fill_rect_params* params
1126 = new(std::nothrow) fill_rect_params[fRectParamsCount];
1127 if (params) {
1128 delete[] fRectParams;
1129 fRectParams = params;
1130 } else {
1131 *count = fRectParamsCount;
1135 for (uint32 i = 0; i < *count; i++) {
1136 clipping_rect r = region->RectAtInt(i);
1137 fRectParams[i].left = (uint16)r.left + fXOffset;
1138 fRectParams[i].top = (uint16)r.top + fYOffset;
1139 fRectParams[i].right = (uint16)r.right + fXOffset;
1140 fRectParams[i].bottom = (uint16)r.bottom + fYOffset;
1145 uint32
1146 DWindowHWInterface::_NativeColor(const rgb_color& color) const
1148 // NOTE: This functions looks somehow suspicios to me.
1149 // It assumes that all graphics cards have the same native endianess, no?
1150 switch (fDisplayMode.space) {
1151 case B_CMAP8:
1152 case B_GRAY8:
1153 return RGBColor(color).GetColor8();
1155 case B_RGB15_BIG:
1156 case B_RGBA15_BIG:
1157 case B_RGB15_LITTLE:
1158 case B_RGBA15_LITTLE:
1159 return RGBColor(color).GetColor15();
1161 case B_RGB16_BIG:
1162 case B_RGB16_LITTLE:
1163 return RGBColor(color).GetColor16();
1165 case B_RGB32_BIG:
1166 case B_RGBA32_BIG:
1167 case B_RGB32_LITTLE:
1168 case B_RGBA32_LITTLE: {
1169 uint32 native = (color.alpha << 24) | (color.red << 16)
1170 | (color.green << 8) | (color.blue);
1171 return native;
1174 return 0;