1/*
2 * Copyright 2005-2012, Haiku.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Stephan A��mus <superstippi@gmx.de>
7 */
8#ifndef HW_INTERFACE_H
9#define HW_INTERFACE_H
10
11
12#include <AutoDeleter.h>
13#include <Accelerant.h>
14#include <GraphicsCard.h>
15#include <List.h>
16#include <Locker.h>
17#include <OS.h>
18#include <Region.h>
19
20#include <video_overlay.h>
21
22#include <new>
23
24#include "IntRect.h"
25#include "MultiLocker.h"
26#include "ServerCursor.h"
27
28
29class BString;
30class DrawingEngine;
31class EventStream;
32class Overlay;
33class RenderingBuffer;
34class ServerBitmap;
35class UpdateQueue;
36
37
38enum {
39	HW_ACC_COPY_REGION					= 0x00000001,
40	HW_ACC_FILL_REGION					= 0x00000002,
41	HW_ACC_INVERT_REGION				= 0x00000004,
42};
43
44
45class HWInterfaceListener {
46public:
47								HWInterfaceListener();
48	virtual						~HWInterfaceListener();
49
50	virtual	void				FrameBufferChanged() {};
51		// Informs a downstream DrawingEngine of a changed framebuffer.
52
53	virtual	void				ScreenChanged(HWInterface* interface) {};
54		// Informs an upstream client of a changed screen configuration.
55};
56
57
58class HWInterface : protected MultiLocker {
59public:
60								HWInterface();
61	virtual						~HWInterface();
62
63	// locking
64			bool				LockParallelAccess() { return ReadLock(); }
65#if DEBUG
66			bool				IsParallelAccessLocked() const
67									{ return IsReadLocked(); }
68#endif
69			void				UnlockParallelAccess() { ReadUnlock(); }
70
71			bool				LockExclusiveAccess() { return WriteLock(); }
72			bool				IsExclusiveAccessLocked()
73									{ return IsWriteLocked(); }
74			void				UnlockExclusiveAccess() { WriteUnlock(); }
75
76	// You need to WriteLock
77	virtual	status_t			Initialize();
78	virtual	status_t			Shutdown() = 0;
79
80	// allocating a DrawingEngine attached to this HWInterface
81	virtual	DrawingEngine*		CreateDrawingEngine();
82
83	// creating an event stream specific for this HWInterface
84	// returns NULL when there is no specific event stream necessary
85	virtual	EventStream*		CreateEventStream();
86
87	// screen mode stuff
88	virtual	status_t			SetMode(const display_mode& mode) = 0;
89	virtual	void				GetMode(display_mode* mode) = 0;
90
91	virtual status_t			GetDeviceInfo(accelerant_device_info* info) = 0;
92	virtual status_t			GetFrameBufferConfig(
93									frame_buffer_config& config) = 0;
94	virtual status_t			GetModeList(display_mode** _modeList,
95									uint32* _count) = 0;
96	virtual status_t			GetPixelClockLimits(display_mode* mode,
97									uint32* _low, uint32* _high) = 0;
98	virtual status_t			GetTimingConstraints(display_timing_constraints*
99									constraints) = 0;
100	virtual status_t			ProposeMode(display_mode* candidate,
101									const display_mode* low,
102									const display_mode* high) = 0;
103	virtual	status_t			GetPreferredMode(display_mode* mode);
104	virtual status_t			GetMonitorInfo(monitor_info* info);
105
106	virtual sem_id				RetraceSemaphore() = 0;
107	virtual status_t			WaitForRetrace(
108									bigtime_t timeout = B_INFINITE_TIMEOUT) = 0;
109
110	virtual status_t			SetDPMSMode(uint32 state) = 0;
111	virtual uint32				DPMSMode() = 0;
112	virtual uint32				DPMSCapabilities() = 0;
113
114	virtual status_t			SetBrightness(float) = 0;
115	virtual status_t			GetBrightness(float*) = 0;
116
117	virtual status_t			GetAccelerantPath(BString& path);
118	virtual status_t			GetDriverPath(BString& path);
119
120	// query for available hardware accleration and perform it
121	// (Initialize() must have been called already)
122	virtual	uint32				AvailableHWAcceleration() const
123									{ return 0; }
124
125	virtual	void				CopyRegion(const clipping_rect* sortedRectList,
126									uint32 count, int32 xOffset, int32 yOffset)
127									{}
128	virtual	void				FillRegion(/*const*/ BRegion& region,
129									const rgb_color& color, bool autoSync) {}
130	virtual	void				InvertRegion(/*const*/ BRegion& region) {}
131
132	virtual	void				Sync() {}
133
134	// cursor handling (these do their own Read/Write locking)
135			ServerCursorReference Cursor() const;
136			ServerCursorReference CursorAndDragBitmap() const;
137	virtual	void				SetCursor(ServerCursor* cursor);
138	virtual	void				SetCursorVisible(bool visible);
139			bool				IsCursorVisible();
140	virtual	void				ObscureCursor();
141	virtual	void				MoveCursorTo(float x, float y);
142			BPoint				CursorPosition();
143
144	virtual	void				SetDragBitmap(const ServerBitmap* bitmap,
145									const BPoint& offsetFromCursor);
146
147	// overlay support
148	virtual overlay_token		AcquireOverlayChannel();
149	virtual void				ReleaseOverlayChannel(overlay_token token);
150
151	virtual status_t			GetOverlayRestrictions(const Overlay* overlay,
152									overlay_restrictions* restrictions);
153	virtual bool				CheckOverlayRestrictions(int32 width,
154									int32 height, color_space colorSpace);
155	virtual const overlay_buffer* AllocateOverlayBuffer(int32 width,
156									int32 height, color_space space);
157	virtual void				FreeOverlayBuffer(const overlay_buffer* buffer);
158
159	virtual void				ConfigureOverlay(Overlay* overlay);
160	virtual void				HideOverlay(Overlay* overlay);
161
162	// frame buffer access (you need to ReadLock!)
163			RenderingBuffer*	DrawingBuffer() const;
164	virtual	RenderingBuffer*	FrontBuffer() const = 0;
165	virtual	RenderingBuffer*	BackBuffer() const = 0;
166			void				SetAsyncDoubleBuffered(bool doubleBuffered);
167	virtual	bool				IsDoubleBuffered() const = 0;
168
169	// Invalidate is used for scheduling an area for updating
170	virtual	status_t			InvalidateRegion(const BRegion& region);
171	virtual	status_t			Invalidate(const BRect& frame);
172	// while as CopyBackToFront() actually performs the operation
173	// either directly or asynchronously by the UpdateQueue thread
174	virtual	status_t			CopyBackToFront(const BRect& frame);
175
176protected:
177	virtual	void				_CopyBackToFront(/*const*/ BRegion& region);
178
179public:
180	// TODO: Just a quick and primitive way to get single buffered mode working.
181	// Later, the implementation should be smarter, right now, it will
182	// draw the cursor for almost every drawing operation.
183	// It seems to me BeOS hides the cursor (in laymans words) before
184	// BView::Draw() is called (if the cursor is within that views clipping region),
185	// then, after all drawing commands that triggered have been caried out,
186	// it shows the cursor again. This approach would have the advantage of
187	// the code not cluttering/slowing down DrawingEngine.
188	// For now, we hide the cursor for any drawing operation that has
189	// a bounding box containing the cursor (in DrawingEngine) so
190	// the cursor hiding is completely transparent from code using DrawingEngine.
191	// ---
192	// NOTE: Investigate locking for these! The client code should already hold a
193	// ReadLock, but maybe these functions should acquire a WriteLock!
194			bool				HideFloatingOverlays(const BRect& area);
195			bool				HideFloatingOverlays();
196			void				ShowFloatingOverlays();
197
198	// Listener support
199			bool				AddListener(HWInterfaceListener* listener);
200			void				RemoveListener(HWInterfaceListener* listener);
201
202protected:
203	// implement this in derived classes
204	virtual	void				_DrawCursor(IntRect area) const;
205
206	// does the actual transfer and handles color space conversion
207			void				_CopyToFront(uint8* src, uint32 srcBPR, int32 x,
208									int32 y, int32 right, int32 bottom) const;
209
210			IntRect				_CursorFrame() const;
211			void				_RestoreCursorArea() const;
212			void				_AdoptDragBitmap();
213
214			void				_NotifyFrameBufferChanged();
215			void				_NotifyScreenChanged();
216
217	static	bool				_IsValidMode(const display_mode& mode);
218
219			// If we draw the cursor somewhere in the drawing buffer,
220			// we need to backup its contents before drawing, so that
221			// we can restore that area when the cursor needs to be
222			// drawn somewhere else.
223			struct buffer_clip {
224				buffer_clip(int32 width, int32 height)
225				{
226					bpr = width * 4;
227					if (bpr > 0 && height > 0)
228						buffer = new(std::nothrow) uint8[bpr * height];
229					else
230						buffer = NULL;
231					left = 0;
232					top = 0;
233					right = -1;
234					bottom = -1;
235					cursor_hidden = true;
236				}
237
238				~buffer_clip()
239				{
240					delete[] buffer;
241				}
242
243				uint8*			buffer;
244				int32			left;
245				int32			top;
246				int32			right;
247				int32			bottom;
248				int32			bpr;
249				bool			cursor_hidden;
250			};
251
252			ObjectDeleter<buffer_clip>
253								fCursorAreaBackup;
254	mutable	BLocker				fFloatingOverlaysLock;
255
256			ServerCursorReference
257								fCursor;
258			BReference<ServerBitmap>
259								fDragBitmap;
260			BPoint				fDragBitmapOffset;
261			ServerCursorReference
262								fCursorAndDragBitmap;
263			bool				fCursorVisible;
264			bool				fCursorObscured;
265			bool				fHardwareCursorEnabled;
266			BPoint				fCursorLocation;
267
268			BRect				fTrackingRect;
269
270			int					fVGADevice;
271
272private:
273			ObjectDeleter<UpdateQueue>
274								fUpdateExecutor;
275
276			BList				fListeners;
277};
278
279#endif // HW_INTERFACE_H
280