///////////////////////////////////////////////////////////////////////////// // Name: wx/dfb/wrapdfb.h // Purpose: wx wrappers for DirectFB interfaces // Author: Vaclav Slavik // Created: 2006-08-23 // RCS-ID: $Id$ // Copyright: (c) 2006 REA Elektronik GmbH // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// #ifndef _WX_DFB_WRAPDFB_H_ #define _WX_DFB_WRAPDFB_H_ #include "wx/dfb/dfbptr.h" #include "wx/gdicmn.h" #include "wx/vidmode.h" #include #include // DFB < 1.0 didn't have u8 type, only __u8 #if DIRECTFB_MAJOR_VERSION == 0 typedef __u8 u8; #endif wxDFB_DECLARE_INTERFACE(IDirectFB); wxDFB_DECLARE_INTERFACE(IDirectFBDisplayLayer); wxDFB_DECLARE_INTERFACE(IDirectFBFont); wxDFB_DECLARE_INTERFACE(IDirectFBWindow); wxDFB_DECLARE_INTERFACE(IDirectFBSurface); wxDFB_DECLARE_INTERFACE(IDirectFBPalette); wxDFB_DECLARE_INTERFACE(IDirectFBEventBuffer); /** Checks the @a code of a DirectFB call and returns true if it was successful and false if it failed, logging the errors as appropriate (asserts for programming errors, wxLogError for runtime failures). */ bool wxDfbCheckReturn(DFBResult code); //----------------------------------------------------------------------------- // wxDfbEvent //----------------------------------------------------------------------------- /** The struct defined by this macro is a thin wrapper around DFB*Event type. It is needed because DFB*Event are typedefs and so we can't forward declare them, but we need to pass them to methods declared in public headers where cannot be included. So this struct just holds the event value, it's sole purpose is that it can be forward declared. */ #define WXDFB_DEFINE_EVENT_WRAPPER(T) \ struct wx##T \ { \ wx##T() {} \ wx##T(const T& event) : m_event(event) {} \ \ operator T&() { return m_event; } \ operator const T&() const { return m_event; } \ T* operator&() { return &m_event; } \ \ DFBEventClass GetClass() const { return m_event.clazz; } \ \ private: \ T m_event; \ }; WXDFB_DEFINE_EVENT_WRAPPER(DFBEvent) WXDFB_DEFINE_EVENT_WRAPPER(DFBWindowEvent) //----------------------------------------------------------------------------- // wxDfbWrapper //----------------------------------------------------------------------------- /// Base class for wxDfbWrapper class wxDfbWrapperBase { public: /// Increases reference count of the object void AddRef() { m_refCnt++; } /// Decreases reference count and if it reaches zero, deletes the object void Release() { if ( --m_refCnt == 0 ) delete this; } /// Returns result code of the last call DFBResult GetLastResult() const { return m_lastResult; } protected: wxDfbWrapperBase() : m_refCnt(1), m_lastResult(DFB_OK) {} /// Dtor may only be called from Release() virtual ~wxDfbWrapperBase() {} /** Checks the @a result of a DirectFB call and returns true if it was successful and false if it failed. Also stores result of the call so that it can be obtained by calling GetLastResult(). */ bool Check(DFBResult result) { m_lastResult = result; return wxDfbCheckReturn(result); } protected: /// Reference count unsigned m_refCnt; /// Result of the last DirectFB call DFBResult m_lastResult; }; /** This template is base class for friendly C++ wrapper around DirectFB interface T. The wrapper provides same API as DirectFB, with a few exceptions: - methods return true/false instead of error code - methods that return or create another interface return pointer to the interface (or NULL on failure) instead of storing it in the last argument - interface arguments use wxFooPtr type instead of raw DirectFB pointer - methods taking flags use int type instead of an enum when the flags can be or-combination of enum elements (this is workaround for C++-unfriendly DirectFB API) */ template class wxDfbWrapper : public wxDfbWrapperBase { public: /// "Raw" DirectFB interface type typedef T DirectFBIface; /// Returns raw DirectFB pointer T *GetRaw() const { return m_ptr; } protected: /// To be called from ctor. Takes ownership of raw object. void Init(T *ptr) { m_ptr = ptr; } /// Dtor may only be used from Release ~wxDfbWrapper() { if ( m_ptr ) m_ptr->Release(m_ptr); } protected: // pointer to DirectFB object T *m_ptr; }; //----------------------------------------------------------------------------- // wxIDirectFBFont //----------------------------------------------------------------------------- struct wxIDirectFBFont : public wxDfbWrapper { wxIDirectFBFont(IDirectFBFont *s) { Init(s); } bool GetStringWidth(const char *text, int bytes, int *w) { return Check(m_ptr->GetStringWidth(m_ptr, text, bytes, w)); } bool GetStringExtents(const char *text, int bytes, DFBRectangle *logicalRect, DFBRectangle *inkRect) { return Check(m_ptr->GetStringExtents(m_ptr, text, bytes, logicalRect, inkRect)); } bool GetHeight(int *h) { return Check(m_ptr->GetHeight(m_ptr, h)); } bool GetDescender(int *descender) { return Check(m_ptr->GetDescender(m_ptr, descender)); } }; //----------------------------------------------------------------------------- // wxIDirectFBPalette //----------------------------------------------------------------------------- struct wxIDirectFBPalette : public wxDfbWrapper { wxIDirectFBPalette(IDirectFBPalette *s) { Init(s); } }; //----------------------------------------------------------------------------- // wxIDirectFBSurface //----------------------------------------------------------------------------- struct wxIDirectFBSurface : public wxDfbWrapper { wxIDirectFBSurface(IDirectFBSurface *s) { Init(s); } bool GetSize(int *w, int *h) { return Check(m_ptr->GetSize(m_ptr, w, h)); } bool GetCapabilities(DFBSurfaceCapabilities *caps) { return Check(m_ptr->GetCapabilities(m_ptr, caps)); } bool GetPixelFormat(DFBSurfacePixelFormat *caps) { return Check(m_ptr->GetPixelFormat(m_ptr, caps)); } // convenience version of GetPixelFormat, returns DSPF_UNKNOWN if fails DFBSurfacePixelFormat GetPixelFormat(); bool SetClip(const DFBRegion *clip) { return Check(m_ptr->SetClip(m_ptr, clip)); } bool SetColor(u8 r, u8 g, u8 b, u8 a) { return Check(m_ptr->SetColor(m_ptr, r, g, b, a)); } bool Clear(u8 r, u8 g, u8 b, u8 a) { return Check(m_ptr->Clear(m_ptr, r, g, b, a)); } bool DrawLine(int x1, int y1, int x2, int y2) { return Check(m_ptr->DrawLine(m_ptr, x1, y1, x2, y2)); } bool DrawRectangle(int x, int y, int w, int h) { return Check(m_ptr->DrawRectangle(m_ptr, x, y, w, h)); } bool FillRectangle(int x, int y, int w, int h) { return Check(m_ptr->FillRectangle(m_ptr, x, y, w, h)); } bool SetFont(const wxIDirectFBFontPtr& font) { return Check(m_ptr->SetFont(m_ptr, font->GetRaw())); } bool DrawString(const char *text, int bytes, int x, int y, int flags) { return Check(m_ptr->DrawString(m_ptr, text, bytes, x, y, (DFBSurfaceTextFlags)flags)); } /** Updates the front buffer from the back buffer. If @a region is not NULL, only given rectangle is updated. */ bool FlipToFront(const DFBRegion *region = NULL); wxIDirectFBSurfacePtr GetSubSurface(const DFBRectangle *rect) { IDirectFBSurface *s; if ( Check(m_ptr->GetSubSurface(m_ptr, rect, &s)) ) return new wxIDirectFBSurface(s); else return NULL; } wxIDirectFBPalettePtr GetPalette() { IDirectFBPalette *s; if ( Check(m_ptr->GetPalette(m_ptr, &s)) ) return new wxIDirectFBPalette(s); else return NULL; } bool SetPalette(const wxIDirectFBPalettePtr& pal) { return Check(m_ptr->SetPalette(m_ptr, pal->GetRaw())); } bool SetBlittingFlags(int flags) { return Check( m_ptr->SetBlittingFlags(m_ptr, (DFBSurfaceBlittingFlags)flags)); } bool Blit(const wxIDirectFBSurfacePtr& source, const DFBRectangle *source_rect, int x, int y) { return Blit(source->GetRaw(), source_rect, x, y); } bool Blit(IDirectFBSurface *source, const DFBRectangle *source_rect, int x, int y) { return Check(m_ptr->Blit(m_ptr, source, source_rect, x, y)); } bool StretchBlit(const wxIDirectFBSurfacePtr& source, const DFBRectangle *source_rect, const DFBRectangle *dest_rect) { return Check(m_ptr->StretchBlit(m_ptr, source->GetRaw(), source_rect, dest_rect)); } /// Returns bit depth used by the surface or -1 on error int GetDepth(); /** Creates a new surface by cloning this one. New surface will have same capabilities, pixel format and pixel data as the existing one. @see CreateCompatible */ wxIDirectFBSurfacePtr Clone(); /// Flags for CreateCompatible() enum CreateCompatibleFlags { /// Don't create double-buffered surface CreateCompatible_NoBackBuffer = 1 }; /** Creates a surface compatible with this one, i.e. surface with the same capabilities and pixel format, but with different and size. @param size Size of the surface to create. If wxDefaultSize, use the size of this surface. @param flags Or-combination of CreateCompatibleFlags values */ wxIDirectFBSurfacePtr CreateCompatible(const wxSize& size = wxDefaultSize, int flags = 0); bool Lock(DFBSurfaceLockFlags flags, void **ret_ptr, int *ret_pitch) { return Check(m_ptr->Lock(m_ptr, flags, ret_ptr, ret_pitch)); } bool Unlock() { return Check(m_ptr->Unlock(m_ptr)); } /// Helper struct for safe locking & unlocking of surfaces struct Locked { Locked(const wxIDirectFBSurfacePtr& surface, DFBSurfaceLockFlags flags) : m_surface(surface) { if ( !surface->Lock(flags, &ptr, &pitch) ) ptr = NULL; } ~Locked() { if ( ptr ) m_surface->Unlock(); } void *ptr; int pitch; private: wxIDirectFBSurfacePtr m_surface; }; private: // this is private because we want user code to use FlipToFront() bool Flip(const DFBRegion *region, int flags); }; //----------------------------------------------------------------------------- // wxIDirectFBEventBuffer //----------------------------------------------------------------------------- struct wxIDirectFBEventBuffer : public wxDfbWrapper { wxIDirectFBEventBuffer(IDirectFBEventBuffer *s) { Init(s); } bool WakeUp() { return Check(m_ptr->WakeUp(m_ptr)); } bool HasEvent() { // returns DFB_OK if there is >=1 event, DFB_BUFFEREMPTY otherwise DFBResult r = m_ptr->HasEvent(m_ptr); // NB: Check() also returns true for DFB_BUFFEREMPTY, so we can't just // return it's return value: Check(r); return (r == DFB_OK); } bool WaitForEventWithTimeout(unsigned secs, unsigned millisecs) { DFBResult r = m_ptr->WaitForEventWithTimeout(m_ptr, secs, millisecs); // DFB_TIMEOUT is not an error in this function: if ( r == DFB_TIMEOUT ) { m_lastResult = DFB_TIMEOUT; return true; } return Check(r); } bool GetEvent(wxDFBEvent& event) { return Check(m_ptr->GetEvent(m_ptr, &event)); } }; //----------------------------------------------------------------------------- // wxIDirectFBWindow //----------------------------------------------------------------------------- struct wxIDirectFBWindow : public wxDfbWrapper { wxIDirectFBWindow(IDirectFBWindow *s) { Init(s); } bool GetID(DFBWindowID *id) { return Check(m_ptr->GetID(m_ptr, id)); } bool GetPosition(int *x, int *y) { return Check(m_ptr->GetPosition(m_ptr, x, y)); } bool GetSize(int *w, int *h) { return Check(m_ptr->GetSize(m_ptr, w, h)); } bool MoveTo(int x, int y) { return Check(m_ptr->MoveTo(m_ptr, x, y)); } bool Resize(int w, int h) { return Check(m_ptr->Resize(m_ptr, w, h)); } bool SetOpacity(u8 opacity) { return Check(m_ptr->SetOpacity(m_ptr, opacity)); } bool SetStackingClass(DFBWindowStackingClass klass) { return Check(m_ptr->SetStackingClass(m_ptr, klass)); } bool RaiseToTop() { return Check(m_ptr->RaiseToTop(m_ptr)); } bool LowerToBottom() { return Check(m_ptr->LowerToBottom(m_ptr)); } wxIDirectFBSurfacePtr GetSurface() { IDirectFBSurface *s; if ( Check(m_ptr->GetSurface(m_ptr, &s)) ) return new wxIDirectFBSurface(s); else return NULL; } bool AttachEventBuffer(const wxIDirectFBEventBufferPtr& buffer) { return Check(m_ptr->AttachEventBuffer(m_ptr, buffer->GetRaw())); } bool RequestFocus() { return Check(m_ptr->RequestFocus(m_ptr)); } bool Destroy() { return Check(m_ptr->Destroy(m_ptr)); } }; //----------------------------------------------------------------------------- // wxIDirectFBDisplayLayer //----------------------------------------------------------------------------- struct wxIDirectFBDisplayLayer : public wxDfbWrapper { wxIDirectFBDisplayLayer(IDirectFBDisplayLayer *s) { Init(s); } wxIDirectFBWindowPtr CreateWindow(const DFBWindowDescription *desc) { IDirectFBWindow *w; if ( Check(m_ptr->CreateWindow(m_ptr, desc, &w)) ) return new wxIDirectFBWindow(w); else return NULL; } bool GetConfiguration(DFBDisplayLayerConfig *config) { return Check(m_ptr->GetConfiguration(m_ptr, config)); } wxVideoMode GetVideoMode(); bool GetCursorPosition(int *x, int *y) { return Check(m_ptr->GetCursorPosition(m_ptr, x, y)); } bool WarpCursor(int x, int y) { return Check(m_ptr->WarpCursor(m_ptr, x, y)); } }; //----------------------------------------------------------------------------- // wxIDirectFB //----------------------------------------------------------------------------- struct wxIDirectFB : public wxDfbWrapper { /** Returns pointer to DirectFB singleton object, it never returns NULL after wxApp was initialized. The object is cached, so calling this method is cheap. */ static wxIDirectFBPtr Get() { if ( !ms_ptr ) CreateDirectFB(); return ms_ptr; } bool SetVideoMode(int w, int h, int bpp) { return Check(m_ptr->SetVideoMode(m_ptr, w, h, bpp)); } wxIDirectFBSurfacePtr CreateSurface(const DFBSurfaceDescription *desc) { IDirectFBSurface *s; if ( Check(m_ptr->CreateSurface(m_ptr, desc, &s)) ) return new wxIDirectFBSurface(s); else return NULL; } wxIDirectFBEventBufferPtr CreateEventBuffer() { IDirectFBEventBuffer *b; if ( Check(m_ptr->CreateEventBuffer(m_ptr, &b)) ) return new wxIDirectFBEventBuffer(b); else return NULL; } wxIDirectFBFontPtr CreateFont(const char *filename, const DFBFontDescription *desc) { IDirectFBFont *f; if ( Check(m_ptr->CreateFont(m_ptr, filename, desc, &f)) ) return new wxIDirectFBFont(f); else return NULL; } wxIDirectFBDisplayLayerPtr GetDisplayLayer(DFBDisplayLayerID id = DLID_PRIMARY) { IDirectFBDisplayLayer *l; if ( Check(m_ptr->GetDisplayLayer(m_ptr, id, &l)) ) return new wxIDirectFBDisplayLayer(l); else return NULL; } /// Returns primary surface wxIDirectFBSurfacePtr GetPrimarySurface(); private: wxIDirectFB(IDirectFB *ptr) { Init(ptr); } // creates ms_ptr instance static void CreateDirectFB(); static void CleanUp(); friend class wxApp; // calls CleanUp // pointer to the singleton IDirectFB object static wxIDirectFBPtr ms_ptr; }; #endif // _WX_DFB_WRAPDFB_H_