2 * Copyright 2006-2012, Haiku. All rights reserved.
3 * Distributed under the terms of the MIT License.
6 * Jérôme Duval, korli@users.berlios.de
7 * Philippe Houdoin, philippe.houdoin@free.fr
8 * Stefano Ceccherini, burton666@libero.it
11 #include <kernel/image.h>
20 #include <DirectWindow.h>
21 #include <GLRenderer.h>
23 #include "interface/DirectWindowPrivate.h"
24 #include "GLDispatcher.h"
25 #include "GLRendererRoster.h"
28 struct glview_direct_info
{
29 direct_buffer_info
* direct_info
;
30 bool direct_connected
;
31 bool enable_direct_mode
;
34 ~glview_direct_info();
38 BGLView::BGLView(BRect rect
, const char* name
, ulong resizingMode
, ulong mode
,
41 BView(rect
, name
, B_FOLLOW_ALL_SIDES
, mode
| B_WILL_DRAW
| B_FRAME_EVENTS
),
42 // | B_FULL_UPDATE_ON_RESIZE)
46 fDrawLock("BGLView draw lock"),
47 fDisplayLock("BGLView display lock"),
53 fRoster
= new GLRendererRoster(this, options
);
54 fRenderer
= fRoster
->GetRenderer();
69 // TODO: acquire the OpenGL API lock it on this glview
72 if (fRenderer
!= NULL
&& fDisplayLock
.CountLocks() == 1)
80 if (fRenderer
!= NULL
&& fDisplayLock
.CountLocks() == 1)
81 fRenderer
->UnlockGL();
82 fDisplayLock
.Unlock();
84 // TODO: release the GL API lock to others glviews
89 BGLView::SwapBuffers()
96 BGLView::SwapBuffers(bool vSync
)
100 fRenderer
->SwapBuffers(vSync
);
107 BGLView::EmbeddedView()
114 BGLView::GetGLProcAddress(const char* procName
)
116 BGLDispatcher
* glDispatcher
= NULL
;
119 glDispatcher
= fRenderer
->GLDispatcher();
122 return (void*)glDispatcher
->AddressOf(procName
);
129 BGLView::CopyPixelsOut(BPoint source
, BBitmap
* dest
)
134 if (!dest
|| !dest
->Bounds().IsValid())
137 return fRenderer
->CopyPixelsOut(source
, dest
);
142 BGLView::CopyPixelsIn(BBitmap
* source
, BPoint dest
)
147 if (!source
|| !source
->Bounds().IsValid())
150 return fRenderer
->CopyPixelsIn(source
, dest
);
154 /*! Mesa's GLenum is not ulong but uint, so we can't use GLenum
155 without breaking this method signature.
156 Instead, we have to use the effective BeOS's SGI OpenGL GLenum type:
160 BGLView::ErrorCallback(unsigned long errorCode
)
163 sprintf(msg
, "GL: Error code $%04lx.", errorCode
);
164 // TODO: under BeOS R5, it call debugger(msg);
165 fprintf(stderr
, "%s\n", msg
);
170 BGLView::Draw(BRect updateRect
)
174 fRenderer
->Draw(updateRect
);
178 // TODO: auto-size and center the string
180 DrawString("No OpenGL renderer available!");
185 BGLView::AttachedToWindow()
187 BView::AttachedToWindow();
190 for (BView
* view
= this; view
!= NULL
; view
= view
->Parent())
191 view
->ConvertToParent(&fBounds
);
193 if (fRenderer
!= NULL
) {
194 // Jackburton: The following code was commented because it doesn't look
195 // good in "direct" mode:
196 // when the window is moved, the app_server doesn't paint the view's
197 // background, and the stuff behind the window itself shows up.
198 // Setting the view color to black, instead, looks a bit more elegant.
200 // Don't paint white window background when resized
201 SetViewColor(B_TRANSPARENT_32_BIT
);
203 SetViewColor(0, 0, 0);
206 // Set default OpenGL viewport:
208 glViewport(0, 0, Bounds().IntegerWidth(), Bounds().IntegerHeight());
210 fRenderer
->FrameResized(Bounds().IntegerWidth(),
211 Bounds().IntegerHeight());
214 fRenderer
->DirectConnected(fClipInfo
->direct_info
);
215 fRenderer
->EnableDirectMode(fClipInfo
->enable_direct_mode
);
221 fprintf(stderr
, "no renderer found! \n");
223 // No Renderer, no rendering. Setup a minimal "No Renderer" string drawing
225 SetFont(be_bold_font
);
231 BGLView::AllAttached()
233 BView::AllAttached();
238 BGLView::DetachedFromWindow()
241 fRenderer
->Release();
244 BView::DetachedFromWindow();
249 BGLView::AllDetached()
251 BView::AllDetached();
256 BGLView::FrameResized(float width
, float height
)
259 for (BView
* v
= this; v
; v
= v
->Parent())
260 v
->ConvertToParent(&fBounds
);
265 _CallDirectConnected();
266 fRenderer
->FrameResized(width
, height
);
271 BView::FrameResized(width
, height
);
276 BGLView::Perform(perform_code d
, void* arg
)
278 return BView::Perform(d
, arg
);
283 BGLView::Archive(BMessage
* data
, bool deep
) const
285 return BView::Archive(data
, deep
);
290 BGLView::MessageReceived(BMessage
* msg
)
292 BView::MessageReceived(msg
);
297 BGLView::SetResizingMode(uint32 mode
)
299 BView::SetResizingMode(mode
);
304 BGLView::GetPreferredSize(float* _width
, float* _height
)
328 BGLView::ResolveSpecifier(BMessage
* msg
, int32 index
, BMessage
* specifier
,
329 int32 form
, const char* property
)
331 return BView::ResolveSpecifier(msg
, index
, specifier
, form
, property
);
336 BGLView::GetSupportedSuites(BMessage
* data
)
338 return BView::GetSupportedSuites(data
);
343 BGLView::DirectConnected(direct_buffer_info
* info
)
345 if (fClipInfo
== NULL
) {
346 fClipInfo
= new (std::nothrow
) glview_direct_info();
347 if (fClipInfo
== NULL
)
351 direct_buffer_info
* localInfo
= fClipInfo
->direct_info
;
353 switch (info
->buffer_state
& B_DIRECT_MODE_MASK
) {
355 fClipInfo
->direct_connected
= true;
356 memcpy(localInfo
, info
, DIRECT_BUFFER_INFO_AREA_SIZE
);
360 case B_DIRECT_MODIFY
:
362 memcpy(localInfo
, info
, DIRECT_BUFFER_INFO_AREA_SIZE
);
367 fClipInfo
->direct_connected
= false;
373 _CallDirectConnected();
378 BGLView::EnableDirectMode(bool enabled
)
381 fRenderer
->EnableDirectMode(enabled
);
382 if (fClipInfo
== NULL
) {
383 fClipInfo
= new (std::nothrow
) glview_direct_info();
384 if (fClipInfo
== NULL
)
388 fClipInfo
->enable_direct_mode
= enabled
;
395 if (!fClipInfo
|| !fClipInfo
->enable_direct_mode
)
403 BGLView::_UnlockDraw()
405 if (!fClipInfo
|| !fClipInfo
->enable_direct_mode
)
413 BGLView::_CallDirectConnected()
418 direct_buffer_info
* localInfo
= fClipInfo
->direct_info
;
419 direct_buffer_info
* info
= (direct_buffer_info
*)malloc(
420 DIRECT_BUFFER_INFO_AREA_SIZE
);
424 memcpy(info
, localInfo
, DIRECT_BUFFER_INFO_AREA_SIZE
);
426 // Collect the rects into a BRegion, then clip to the view's bounds
428 for (uint32 c
= 0; c
< localInfo
->clip_list_count
; c
++)
429 region
.Include(localInfo
->clip_list
[c
]);
430 BRegion boundsRegion
= fBounds
.OffsetByCopy(localInfo
->window_bounds
.left
,
431 localInfo
->window_bounds
.top
);
432 info
->window_bounds
= boundsRegion
.RectAtInt(0);
433 // window_bounds are now view bounds
434 region
.IntersectWith(&boundsRegion
);
436 info
->clip_list_count
= region
.CountRects();
437 info
->clip_bounds
= region
.FrameInt();
439 for (uint32 c
= 0; c
< info
->clip_list_count
; c
++)
440 info
->clip_list
[c
] = region
.RectAtInt(c
);
441 fRenderer
->DirectConnected(info
);
446 //---- virtual reserved methods ----------
449 void BGLView::_ReservedGLView1() {}
450 void BGLView::_ReservedGLView2() {}
451 void BGLView::_ReservedGLView3() {}
452 void BGLView::_ReservedGLView4() {}
453 void BGLView::_ReservedGLView5() {}
454 void BGLView::_ReservedGLView6() {}
455 void BGLView::_ReservedGLView7() {}
456 void BGLView::_ReservedGLView8() {}
462 // BeOS compatibility: contrary to others BView's contructors,
463 // BGLView one wants a non-const name argument.
464 BGLView::BGLView(BRect rect
, char* name
, ulong resizingMode
, ulong mode
,
467 BView(rect
, name
, B_FOLLOW_ALL_SIDES
, mode
| B_WILL_DRAW
| B_FRAME_EVENTS
),
471 fDrawLock("BGLView draw lock"),
472 fDisplayLock("BGLView display lock"),
478 fRoster
= new GLRendererRoster(this, options
);
483 // TODO: implement BGLScreen class...
486 BGLScreen::BGLScreen(char* name
, ulong screenMode
, ulong options
,
487 status_t
* error
, bool debug
)
489 BWindowScreen(name
, screenMode
, error
, debug
)
494 BGLScreen::~BGLScreen()
506 BGLScreen::UnlockGL()
512 BGLScreen::SwapBuffers()
518 BGLScreen::ErrorCallback(unsigned long errorCode
)
520 // Mesa's GLenum is not ulong but uint!
522 sprintf(msg
, "GL: Error code $%04lx.", errorCode
);
524 fprintf(stderr
, "%s\n", msg
);
530 BGLScreen::ScreenConnected(bool enabled
)
536 BGLScreen::FrameResized(float width
, float height
)
538 return BWindowScreen::FrameResized(width
, height
);
543 BGLScreen::Perform(perform_code d
, void* arg
)
545 return BWindowScreen::Perform(d
, arg
);
550 BGLScreen::Archive(BMessage
* data
, bool deep
) const
552 return BWindowScreen::Archive(data
, deep
);
557 BGLScreen::MessageReceived(BMessage
* msg
)
559 BWindowScreen::MessageReceived(msg
);
566 BWindowScreen::Show();
573 BWindowScreen::Hide();
578 BGLScreen::ResolveSpecifier(BMessage
* msg
, int32 index
, BMessage
* specifier
,
579 int32 form
, const char* property
)
581 return BWindowScreen::ResolveSpecifier(msg
, index
, specifier
,
587 BGLScreen::GetSupportedSuites(BMessage
* data
)
589 return BWindowScreen::GetSupportedSuites(data
);
593 //---- virtual reserved methods ----------
595 void BGLScreen::_ReservedGLScreen1() {}
596 void BGLScreen::_ReservedGLScreen2() {}
597 void BGLScreen::_ReservedGLScreen3() {}
598 void BGLScreen::_ReservedGLScreen4() {}
599 void BGLScreen::_ReservedGLScreen5() {}
600 void BGLScreen::_ReservedGLScreen6() {}
601 void BGLScreen::_ReservedGLScreen7() {}
602 void BGLScreen::_ReservedGLScreen8() {}
606 const char* color_space_name(color_space space
)
608 #define C2N(a) case a: return #a
630 glview_direct_info::glview_direct_info()
632 // TODO: See direct_window_data() in app_server's ServerWindow.cpp
633 direct_info
= (direct_buffer_info
*)calloc(1, DIRECT_BUFFER_INFO_AREA_SIZE
);
634 direct_connected
= false;
635 enable_direct_mode
= false;
639 glview_direct_info::~glview_direct_info()