2 * Copyright 2005-2012, Haiku.
3 * Distributed under the terms of the MIT License.
6 * Stephan Aßmus <superstippi@gmx.de>
10 #include "HWInterface.h"
17 #include <vesa/vesa_info.h>
19 #include "drawing_support.h"
21 #include "DrawingEngine.h"
22 #include "RenderingBuffer.h"
23 #include "SystemPalette.h"
24 #include "UpdateQueue.h"
30 HWInterfaceListener::HWInterfaceListener()
35 HWInterfaceListener::~HWInterfaceListener()
40 // #pragma mark - HWInterface
43 HWInterface::HWInterface(bool doubleBuffered
, bool enableUpdateQueue
)
45 MultiLocker("hw interface lock"),
46 fCursorAreaBackup(NULL
),
47 fFloatingOverlaysLock("floating overlays lock"),
50 fDragBitmapOffset(0, 0),
51 fCursorAndDragBitmap(NULL
),
52 fCursorVisible(false),
53 fCursorObscured(false),
54 fHardwareCursorEnabled(false),
55 fCursorLocation(0, 0),
56 fDoubleBuffered(doubleBuffered
),
58 fUpdateExecutor(NULL
),
61 SetAsyncDoubleBuffered(doubleBuffered
&& enableUpdateQueue
);
65 HWInterface::~HWInterface()
67 SetAsyncDoubleBuffered(false);
69 delete fCursorAreaBackup
;
71 // The standard cursor doesn't belong us - the drag bitmap might
72 if (fCursor
!= fCursorAndDragBitmap
)
73 delete fCursorAndDragBitmap
;
78 HWInterface::Initialize()
80 return MultiLocker::InitCheck();
85 HWInterface::CreateDrawingEngine()
87 return new(std::nothrow
) DrawingEngine(this);
92 HWInterface::CreateEventStream()
99 HWInterface::GetAccelerantPath(BString
&path
)
106 HWInterface::GetDriverPath(BString
&path
)
113 HWInterface::GetPreferredMode(display_mode
* mode
)
115 return B_NOT_SUPPORTED
;
120 HWInterface::GetMonitorInfo(monitor_info
* info
)
122 return B_NOT_SUPPORTED
;
130 HWInterface::SetCursor(ServerCursor
* cursor
)
132 if (!fFloatingOverlaysLock
.Lock())
135 if (fCursor
!= cursor
) {
136 BRect oldFrame
= _CursorFrame();
138 if (fCursorAndDragBitmap
== fCursor
) {
139 // make sure _AdoptDragBitmap doesn't delete a real cursor
140 fCursorAndDragBitmap
= NULL
;
144 fCursor
->ReleaseReference();
149 fCursor
->AcquireReference();
151 Invalidate(oldFrame
);
153 _AdoptDragBitmap(fDragBitmap
, fDragBitmapOffset
);
154 Invalidate(_CursorFrame());
156 fFloatingOverlaysLock
.Unlock();
160 ServerCursorReference
161 HWInterface::Cursor() const
163 if (!fFloatingOverlaysLock
.Lock())
164 return ServerCursorReference(NULL
);
166 ServerCursorReference
reference(fCursor
);
167 fFloatingOverlaysLock
.Unlock();
172 ServerCursorReference
173 HWInterface::CursorAndDragBitmap() const
175 if (!fFloatingOverlaysLock
.Lock())
176 return ServerCursorReference(NULL
);
178 ServerCursorReference
reference(fCursorAndDragBitmap
);
179 fFloatingOverlaysLock
.Unlock();
185 HWInterface::SetCursorVisible(bool visible
)
187 if (!fFloatingOverlaysLock
.Lock())
190 if (fCursorVisible
!= visible
) {
191 // NOTE: _CursorFrame() will
192 // return an invalid rect if
193 // fCursorVisible == false!
195 fCursorVisible
= visible
;
196 fCursorObscured
= false;
197 IntRect r
= _CursorFrame();
202 IntRect r
= _CursorFrame();
203 fCursorVisible
= visible
;
205 _RestoreCursorArea();
209 fFloatingOverlaysLock
.Unlock();
214 HWInterface::IsCursorVisible()
217 if (fFloatingOverlaysLock
.Lock()) {
218 visible
= fCursorVisible
;
219 fFloatingOverlaysLock
.Unlock();
226 HWInterface::ObscureCursor()
228 if (!fFloatingOverlaysLock
.Lock())
231 if (!fCursorObscured
) {
232 SetCursorVisible(false);
233 fCursorObscured
= true;
235 fFloatingOverlaysLock
.Unlock();
240 HWInterface::MoveCursorTo(float x
, float y
)
242 if (!fFloatingOverlaysLock
.Lock())
246 if (p
!= fCursorLocation
) {
247 // unhide cursor if it is obscured only
248 if (fCursorObscured
) {
249 SetCursorVisible(true);
251 IntRect oldFrame
= _CursorFrame();
253 if (fCursorVisible
) {
254 // Invalidate and _DrawCursor would not draw
255 // anything if the cursor is hidden
256 // (invalid cursor frame), but explicitly
257 // testing for it here saves us some cycles
258 if (fCursorAreaBackup
) {
259 // means we have a software cursor which we need to draw
260 _RestoreCursorArea();
261 _DrawCursor(_CursorFrame());
263 IntRect newFrame
= _CursorFrame();
264 if (newFrame
.Intersects(oldFrame
))
265 Invalidate(oldFrame
| newFrame
);
267 Invalidate(oldFrame
);
268 Invalidate(newFrame
);
272 fFloatingOverlaysLock
.Unlock();
277 HWInterface::CursorPosition()
280 if (fFloatingOverlaysLock
.Lock()) {
281 location
= fCursorLocation
;
282 fFloatingOverlaysLock
.Unlock();
289 HWInterface::SetDragBitmap(const ServerBitmap
* bitmap
,
290 const BPoint
& offsetFromCursor
)
292 if (fFloatingOverlaysLock
.Lock()) {
293 _AdoptDragBitmap(bitmap
, offsetFromCursor
);
294 fFloatingOverlaysLock
.Unlock();
303 HWInterface::DrawingBuffer() const
305 if (IsDoubleBuffered())
307 return FrontBuffer();
312 HWInterface::SetAsyncDoubleBuffered(bool doubleBuffered
)
314 if (doubleBuffered
) {
315 if (fUpdateExecutor
!= NULL
)
317 fUpdateExecutor
= new (nothrow
) UpdateQueue(this);
318 AddListener(fUpdateExecutor
);
320 if (fUpdateExecutor
== NULL
)
322 RemoveListener(fUpdateExecutor
);
323 delete fUpdateExecutor
;
324 fUpdateExecutor
= NULL
;
330 HWInterface::IsDoubleBuffered() const
332 return fDoubleBuffered
;
336 /*! The object needs to be already locked!
339 HWInterface::InvalidateRegion(BRegion
& region
)
341 int32 count
= region
.CountRects();
342 for (int32 i
= 0; i
< count
; i
++) {
343 status_t result
= Invalidate(region
.RectAt(i
));
352 /*! The object needs to be already locked!
355 HWInterface::Invalidate(const BRect
& frame
)
357 if (IsDoubleBuffered()) {
359 // NOTE: The UpdateQueue works perfectly fine, but it screws the
360 // flicker-free-ness of the double buffered rendering. The problem being the
361 // asynchronous nature. The UpdateQueue will transfer regions of the screen
362 // which have been clean at the time we are in this function, but which have
363 // been damaged meanwhile by drawing into them again. All in all, the
364 // UpdateQueue is good for reducing the number of times that the transfer
365 // is performed, and makes it happen during refresh only, but until there
366 // is a smarter way to synchronize this all better, I've disabled it.
367 if (fUpdateExecutor
!= NULL
) {
368 fUpdateExecutor
->AddRect(frame
);
372 return CopyBackToFront(frame
);
378 /*! The object must already be locked!
381 HWInterface::CopyBackToFront(const BRect
& frame
)
383 RenderingBuffer
* frontBuffer
= FrontBuffer();
384 RenderingBuffer
* backBuffer
= BackBuffer();
386 if (!backBuffer
|| !frontBuffer
)
389 // we need to mess with the area, but it is const
391 IntRect
bufferClip(backBuffer
->Bounds());
393 if (area
.IsValid() && area
.Intersects(bufferClip
)) {
395 // make sure we don't copy out of bounds
396 area
= bufferClip
& area
;
398 bool cursorLocked
= fFloatingOverlaysLock
.Lock();
400 BRegion
region((BRect
)area
);
401 if (IsDoubleBuffered())
402 region
.Exclude((clipping_rect
)_CursorFrame());
404 _CopyBackToFront(region
);
409 fFloatingOverlaysLock
.Unlock();
418 HWInterface::_CopyBackToFront(/*const*/ BRegion
& region
)
420 RenderingBuffer
* backBuffer
= BackBuffer();
422 uint32 srcBPR
= backBuffer
->BytesPerRow();
423 uint8
* src
= (uint8
*)backBuffer
->Bits();
425 int32 count
= region
.CountRects();
426 for (int32 i
= 0; i
< count
; i
++) {
427 clipping_rect r
= region
.RectAtInt(i
);
428 // offset to left top pixel in source buffer (always B_RGBA32)
429 uint8
* srcOffset
= src
+ r
.top
* srcBPR
+ r
.left
* 4;
430 _CopyToFront(srcOffset
, srcBPR
, r
.left
, r
.top
, r
.right
, r
.bottom
);
439 HWInterface::AcquireOverlayChannel()
446 HWInterface::ReleaseOverlayChannel(overlay_token token
)
452 HWInterface::GetOverlayRestrictions(const Overlay
* overlay
,
453 overlay_restrictions
* restrictions
)
455 return B_NOT_SUPPORTED
;
460 HWInterface::CheckOverlayRestrictions(int32 width
, int32 height
,
461 color_space colorSpace
)
467 const overlay_buffer
*
468 HWInterface::AllocateOverlayBuffer(int32 width
, int32 height
, color_space space
)
475 HWInterface::FreeOverlayBuffer(const overlay_buffer
* buffer
)
481 HWInterface::ConfigureOverlay(Overlay
* overlay
)
487 HWInterface::HideOverlay(Overlay
* overlay
)
496 HWInterface::HideFloatingOverlays(const BRect
& area
)
498 if (IsDoubleBuffered())
500 if (!fFloatingOverlaysLock
.Lock())
502 if (fCursorAreaBackup
&& !fCursorAreaBackup
->cursor_hidden
) {
503 BRect
backupArea(fCursorAreaBackup
->left
, fCursorAreaBackup
->top
,
504 fCursorAreaBackup
->right
, fCursorAreaBackup
->bottom
);
505 if (area
.Intersects(backupArea
)) {
506 _RestoreCursorArea();
507 // do not unlock the cursor lock
511 fFloatingOverlaysLock
.Unlock();
517 HWInterface::HideFloatingOverlays()
519 if (IsDoubleBuffered())
521 if (!fFloatingOverlaysLock
.Lock())
524 _RestoreCursorArea();
530 HWInterface::ShowFloatingOverlays()
532 if (fCursorAreaBackup
&& fCursorAreaBackup
->cursor_hidden
)
533 _DrawCursor(_CursorFrame());
535 fFloatingOverlaysLock
.Unlock();
543 HWInterface::AddListener(HWInterfaceListener
* listener
)
545 if (listener
&& !fListeners
.HasItem(listener
))
546 return fListeners
.AddItem(listener
);
552 HWInterface::RemoveListener(HWInterfaceListener
* listener
)
554 fListeners
.RemoveItem(listener
);
561 /*! Default implementation, can be used as fallback or for software cursor.
562 \param area is where we potentially draw the cursor, the cursor
563 might be somewhere else, in which case this function does nothing
566 HWInterface::_DrawCursor(IntRect area
) const
568 RenderingBuffer
* backBuffer
= DrawingBuffer();
569 if (!backBuffer
|| !area
.IsValid())
572 IntRect cf
= _CursorFrame();
574 // make sure we don't copy out of bounds
575 area
= backBuffer
->Bounds() & area
;
577 if (cf
.IsValid() && area
.Intersects(cf
)) {
579 // clip to common area
582 int32 width
= area
.right
- area
.left
+ 1;
583 int32 height
= area
.bottom
- area
.top
+ 1;
585 // make a bitmap from the backbuffer
586 // that has the cursor blended on top of it
589 uint8
* buffer
= new uint8
[width
* height
* 4];
590 // TODO: cache this buffer
592 // offset into back buffer
593 uint8
* src
= (uint8
*)backBuffer
->Bits();
594 uint32 srcBPR
= backBuffer
->BytesPerRow();
595 src
+= area
.top
* srcBPR
+ area
.left
* 4;
597 // offset into cursor bitmap
598 uint8
* crs
= (uint8
*)fCursorAndDragBitmap
->Bits();
599 uint32 crsBPR
= fCursorAndDragBitmap
->BytesPerRow();
600 // since area is clipped to cf,
601 // the diff between area.top and cf.top is always positive,
602 // same for diff between area.left and cf.left
603 crs
+= (area
.top
- (int32
)floorf(cf
.top
)) * crsBPR
604 + (area
.left
- (int32
)floorf(cf
.left
)) * 4;
608 if (fCursorAreaBackup
&& fCursorAreaBackup
->buffer
609 && fFloatingOverlaysLock
.Lock()) {
610 fCursorAreaBackup
->cursor_hidden
= false;
611 // remember which area the backup contains
612 fCursorAreaBackup
->left
= area
.left
;
613 fCursorAreaBackup
->top
= area
.top
;
614 fCursorAreaBackup
->right
= area
.right
;
615 fCursorAreaBackup
->bottom
= area
.bottom
;
616 uint8
* bup
= fCursorAreaBackup
->buffer
;
617 uint32 bupBPR
= fCursorAreaBackup
->bpr
;
619 // blending and backup of drawing buffer
620 for (int32 y
= area
.top
; y
<= area
.bottom
; y
++) {
626 for (int32 x
= area
.left
; x
<= area
.right
; x
++) {
627 *(uint32
*)b
= *(uint32
*)s
;
628 // assumes backbuffer alpha = 255
629 // assuming pre-multiplied cursor bitmap
631 d
[0] = ((int)(b
[0] * a
+ 255) >> 8) + c
[0];
632 d
[1] = ((int)(b
[1] * a
+ 255) >> 8) + c
[1];
633 d
[2] = ((int)(b
[2] * a
+ 255) >> 8) + c
[2];
645 fFloatingOverlaysLock
.Unlock();
648 for (int32 y
= area
.top
; y
<= area
.bottom
; y
++) {
652 for (int32 x
= area
.left
; x
<= area
.right
; x
++) {
653 // assumes backbuffer alpha = 255
654 // assuming pre-multiplied cursor bitmap
655 uint8 a
= 255 - c
[3];
656 d
[0] = ((s
[0] * a
+ 255) >> 8) + c
[0];
657 d
[1] = ((s
[1] * a
+ 255) >> 8) + c
[1];
658 d
[2] = ((s
[2] * a
+ 255) >> 8) + c
[2];
669 // copy result to front buffer
670 _CopyToFront(buffer
, width
* 4, area
.left
, area
.top
, area
.right
,
678 /*! - source is assumed to be already at the right offset
679 - source is assumed to be in B_RGBA32 format
680 - location in front buffer is calculated
681 - conversion from B_RGBA32 to format of front buffer is taken care of
684 HWInterface::_CopyToFront(uint8
* src
, uint32 srcBPR
, int32 x
, int32 y
,
685 int32 right
, int32 bottom
) const
687 RenderingBuffer
* frontBuffer
= FrontBuffer();
689 uint8
* dst
= (uint8
*)frontBuffer
->Bits();
690 uint32 dstBPR
= frontBuffer
->BytesPerRow();
692 // transfer, handle colorspace conversion
693 switch (frontBuffer
->ColorSpace()) {
697 int32 bytes
= (right
- x
+ 1) * 4;
700 // offset to left top pixel in dest buffer
701 dst
+= y
* dstBPR
+ x
* 4;
703 for (; y
<= bottom
; y
++) {
704 // bytes is guaranteed to be multiple of 4
705 gfxcpy32(dst
, src
, bytes
);
715 // offset to left top pixel in dest buffer
716 dst
+= y
* dstBPR
+ x
* 3;
719 for (; y
<= bottom
; y
++) {
720 uint8
* srcHandle
= src
;
721 uint8
* dstHandle
= dst
;
722 for (x
= left
; x
<= right
; x
++) {
723 dstHandle
[0] = srcHandle
[0];
724 dstHandle
[1] = srcHandle
[1];
725 dstHandle
[2] = srcHandle
[2];
737 // offset to left top pixel in dest buffer
738 dst
+= y
* dstBPR
+ x
* 2;
741 // TODO: assumes BGR order, does this work on big endian as well?
742 for (; y
<= bottom
; y
++) {
743 uint8
* srcHandle
= src
;
744 uint16
* dstHandle
= (uint16
*)dst
;
745 for (x
= left
; x
<= right
; x
++) {
746 *dstHandle
= (uint16
)(((srcHandle
[2] & 0xf8) << 8)
747 | ((srcHandle
[1] & 0xfc) << 3) | (srcHandle
[0] >> 3));
760 // offset to left top pixel in dest buffer
761 dst
+= y
* dstBPR
+ x
* 2;
764 // TODO: assumes BGR order, does this work on big endian as well?
765 for (; y
<= bottom
; y
++) {
766 uint8
* srcHandle
= src
;
767 uint16
* dstHandle
= (uint16
*)dst
;
768 for (x
= left
; x
<= right
; x
++) {
769 *dstHandle
= (uint16
)(((srcHandle
[2] & 0xf8) << 7)
770 | ((srcHandle
[1] & 0xf8) << 2) | (srcHandle
[0] >> 3));
782 const color_map
*colorMap
= SystemColorMap();
783 // offset to left top pixel in dest buffer
784 dst
+= y
* dstBPR
+ x
;
788 // TODO: assumes BGR order again
789 for (; y
<= bottom
; y
++) {
790 uint8
* srcHandle
= src
;
791 uint8
* dstHandle
= dst
;
792 for (x
= left
; x
<= right
; x
++) {
793 index
= ((srcHandle
[2] & 0xf8) << 7)
794 | ((srcHandle
[1] & 0xf8) << 2) | (srcHandle
[0] >> 3);
795 *dstHandle
= colorMap
->index_map
[index
];
807 if (frontBuffer
->Width() > dstBPR
) {
808 // VGA 16 color grayscale planar mode
809 if (fVGADevice
>= 0) {
810 vga_planar_blit_args args
;
812 args
.source_bytes_per_row
= srcBPR
;
816 args
.bottom
= bottom
;
817 if (ioctl(fVGADevice
, VGA_PLANAR_BLIT
, &args
, sizeof(args
))
822 // Since we cannot set the plane, we do monochrome output
823 dst
+= y
* dstBPR
+ x
/ 8;
826 // TODO: this is awfully slow...
827 // TODO: assumes BGR order
828 for (; y
<= bottom
; y
++) {
829 uint8
* srcHandle
= src
;
830 uint8
* dstHandle
= dst
;
831 uint8 current8
= dstHandle
[0];
832 // we store 8 pixels before writing them back
834 for (x
= left
; x
<= right
; x
++) {
835 uint8 pixel
= (308 * srcHandle
[2] + 600 * srcHandle
[1]
836 + 116 * srcHandle
[0]) / 1024;
840 current8
|= 0x80 >> (x
& 7);
842 current8
&= ~(0x80 >> (x
& 7));
845 // last pixel in 8 pixel group
846 dstHandle
[0] = current8
;
848 current8
= dstHandle
[0];
853 // last pixel has not been written yet
854 dstHandle
[0] = current8
;
860 // offset to left top pixel in dest buffer
861 dst
+= y
* dstBPR
+ x
;
864 // TODO: assumes BGR order, does this work on big endian as well?
865 for (; y
<= bottom
; y
++) {
866 uint8
* srcHandle
= src
;
867 uint8
* dstHandle
= dst
;
868 for (x
= left
; x
<= right
; x
++) {
869 *dstHandle
= (308 * srcHandle
[2] + 600 * srcHandle
[1]
870 + 116 * srcHandle
[0]) / 1024;
881 fprintf(stderr
, "HWInterface::CopyBackToFront() - unsupported "
882 "front buffer format! (0x%x)\n", frontBuffer
->ColorSpace());
888 /*! The object must be locked
891 HWInterface::_CursorFrame() const
893 IntRect
frame(0, 0, -1, -1);
894 if (fCursorAndDragBitmap
&& fCursorVisible
&& !fHardwareCursorEnabled
) {
895 frame
= fCursorAndDragBitmap
->Bounds();
896 frame
.OffsetTo(fCursorLocation
- fCursorAndDragBitmap
->GetHotSpot());
903 HWInterface::_RestoreCursorArea() const
905 if (fCursorAreaBackup
&& !fCursorAreaBackup
->cursor_hidden
) {
906 _CopyToFront(fCursorAreaBackup
->buffer
, fCursorAreaBackup
->bpr
,
907 fCursorAreaBackup
->left
, fCursorAreaBackup
->top
,
908 fCursorAreaBackup
->right
, fCursorAreaBackup
->bottom
);
910 fCursorAreaBackup
->cursor_hidden
= true;
916 HWInterface::_AdoptDragBitmap(const ServerBitmap
* bitmap
, const BPoint
& offset
)
918 // TODO: support other colorspaces/convert bitmap
919 if (bitmap
&& !(bitmap
->ColorSpace() == B_RGB32
920 || bitmap
->ColorSpace() == B_RGBA32
)) {
921 fprintf(stderr
, "HWInterface::_AdoptDragBitmap() - bitmap has yet "
922 "unsupported colorspace\n");
926 _RestoreCursorArea();
927 BRect oldCursorFrame
= _CursorFrame();
929 if (fCursorAndDragBitmap
&& fCursorAndDragBitmap
!= fCursor
) {
930 delete fCursorAndDragBitmap
;
931 fCursorAndDragBitmap
= NULL
;
934 if (bitmap
!= NULL
&& bitmap
->Bounds().Width() > 0 && bitmap
->Bounds().Height() > 0) {
935 BRect bitmapFrame
= bitmap
->Bounds();
937 // put bitmap frame and cursor frame into the same
938 // coordinate space (the cursor location is the origin)
939 bitmapFrame
.OffsetTo(BPoint(-offset
.x
, -offset
.y
));
941 BRect
cursorFrame(fCursor
->Bounds());
942 BPoint
hotspot(fCursor
->GetHotSpot());
943 // the hotspot is at the origin
944 cursorFrame
.OffsetTo(-hotspot
.x
, -hotspot
.y
);
946 BRect combindedBounds
= bitmapFrame
| cursorFrame
;
949 shift
.x
= -combindedBounds
.left
;
950 shift
.y
= -combindedBounds
.top
;
952 combindedBounds
.OffsetBy(shift
);
953 cursorFrame
.OffsetBy(shift
);
954 bitmapFrame
.OffsetBy(shift
);
956 fCursorAndDragBitmap
= new(std::nothrow
) ServerCursor(combindedBounds
,
957 bitmap
->ColorSpace(), 0, shift
);
959 uint8
* dst
= fCursorAndDragBitmap
? (uint8
*)fCursorAndDragBitmap
->Bits() : NULL
;
961 // Oops, we could not allocate memory for the drag bitmap.
962 // Let's show the cursor only.
963 delete fCursorAndDragBitmap
;
964 fCursorAndDragBitmap
= fCursor
;
966 // clear the combined buffer
967 uint32 dstBPR
= fCursorAndDragBitmap
->BytesPerRow();
969 memset(dst
, 0, fCursorAndDragBitmap
->BitsLength());
971 // put drag bitmap into combined buffer
972 uint8
* src
= (uint8
*)bitmap
->Bits();
973 uint32 srcBPR
= bitmap
->BytesPerRow();
975 dst
+= (int32
)bitmapFrame
.top
* dstBPR
976 + (int32
)bitmapFrame
.left
* 4;
978 uint32 width
= bitmapFrame
.IntegerWidth() + 1;
979 uint32 height
= bitmapFrame
.IntegerHeight() + 1;
981 for (uint32 y
= 0; y
< height
; y
++) {
982 memcpy(dst
, src
, srcBPR
);
987 // compose cursor into combined buffer
988 dst
= (uint8
*)fCursorAndDragBitmap
->Bits();
989 dst
+= (int32
)cursorFrame
.top
* dstBPR
990 + (int32
)cursorFrame
.left
* 4;
992 src
= (uint8
*)fCursor
->Bits();
993 srcBPR
= fCursor
->BytesPerRow();
995 width
= cursorFrame
.IntegerWidth() + 1;
996 height
= cursorFrame
.IntegerHeight() + 1;
998 for (uint32 y
= 0; y
< height
; y
++) {
1001 for (uint32 x
= 0; x
< width
; x
++) {
1002 // takes two semi-transparent pixels
1003 // with unassociated alpha (not pre-multiplied)
1004 // and stays within non-premultiplied color space
1012 uint8 alphaRest
= 255 - s
[3];
1014 = (65025 - alphaRest
* (255 - d
[3]));
1015 uint32 alphaDest
= d
[3] * alphaRest
;
1016 uint32 alphaSrc
= 255 * s
[3];
1017 d
[0] = (d
[0] * alphaDest
+ s
[0] * alphaSrc
)
1019 d
[1] = (d
[1] * alphaDest
+ s
[1] * alphaSrc
)
1021 d
[2] = (d
[2] * alphaDest
+ s
[2] * alphaSrc
)
1023 d
[3] = alphaTemp
/ 255;
1026 // TODO: make sure the alpha is always upside down,
1027 // then it doesn't need to be done when drawing the cursor
1028 // (see _DrawCursor())
1029 // d[3] = 255 - d[3];
1037 // handle pre-multiplication with alpha
1038 // for faster compositing during cursor drawing
1039 width
= combindedBounds
.IntegerWidth() + 1;
1040 height
= combindedBounds
.IntegerHeight() + 1;
1042 dst
= (uint8
*)fCursorAndDragBitmap
->Bits();
1044 for (uint32 y
= 0; y
< height
; y
++) {
1046 for (uint32 x
= 0; x
< width
; x
++) {
1047 d
[0] = (d
[0] * d
[3]) >> 8;
1048 d
[1] = (d
[1] * d
[3]) >> 8;
1049 d
[2] = (d
[2] * d
[3]) >> 8;
1056 fCursorAndDragBitmap
= new ServerCursor(bitmap
->Bits(),
1057 bitmapFrame
.IntegerWidth() + 1, bitmapFrame
.IntegerHeight() + 1,
1058 bitmap
->ColorSpace());
1059 fCursorAndDragBitmap
->SetHotSpot(BPoint(-offset
.x
, -offset
.y
));
1062 fCursorAndDragBitmap
= fCursor
;
1065 Invalidate(oldCursorFrame
);
1067 // NOTE: the EventDispatcher does the reference counting stuff for us
1068 // TODO: You can not simply call Release() on a ServerBitmap like you
1069 // can for a ServerCursor... it could be changed, but there are linking
1070 // troubles with the test environment that need to be solved than.
1072 // fDragBitmap->Release();
1073 fDragBitmap
= bitmap
;
1074 fDragBitmapOffset
= offset
;
1076 // fDragBitmap->Acquire();
1078 delete fCursorAreaBackup
;
1079 fCursorAreaBackup
= NULL
;
1081 if (!fCursorAndDragBitmap
)
1084 if (fCursorAndDragBitmap
&& !IsDoubleBuffered()) {
1085 BRect cursorBounds
= fCursorAndDragBitmap
->Bounds();
1086 fCursorAreaBackup
= new buffer_clip(cursorBounds
.IntegerWidth() + 1,
1087 cursorBounds
.IntegerHeight() + 1);
1089 _DrawCursor(_CursorFrame());
1094 HWInterface::_NotifyFrameBufferChanged()
1096 BList
listeners(fListeners
);
1097 int32 count
= listeners
.CountItems();
1098 for (int32 i
= 0; i
< count
; i
++) {
1099 HWInterfaceListener
* listener
1100 = (HWInterfaceListener
*)listeners
.ItemAtFast(i
);
1101 listener
->FrameBufferChanged();
1107 HWInterface::_NotifyScreenChanged()
1109 BList
listeners(fListeners
);
1110 int32 count
= listeners
.CountItems();
1111 for (int32 i
= 0; i
< count
; i
++) {
1112 HWInterfaceListener
* listener
1113 = (HWInterfaceListener
*)listeners
.ItemAtFast(i
);
1114 listener
->ScreenChanged(this);
1120 HWInterface::_IsValidMode(const display_mode
& mode
)
1122 // TODO: more of those!
1123 if (mode
.virtual_width
< 320
1124 || mode
.virtual_height
< 200)