diff options
author | Alexander von Gluck IV <[email protected]> | 2013-12-31 15:39:49 -0600 |
---|---|---|
committer | Alexander von Gluck IV <[email protected]> | 2014-01-06 15:50:21 -0600 |
commit | 61ef697afc0ad509dcabdecfc424f27b5966969c (patch) | |
tree | b099044ff97e9a0f4522b8c59adaaec82d6ace28 /src/hgl/GLView.cpp | |
parent | b236314a1107214210c429295fac8a5bdf457772 (diff) |
haiku libGL: Move from gallium target to src/hgl
* The Haiku renderers need to link to libGL to function properly
in all usage contexts. As mesa drivers build before gallium
targets, we couldn't properly link the mesa swrast driver to
the gallium libGL target for Haiku.
* This is likely better as it mimics how glx is laid out ensuring
the Haiku libGL is better understood.
* All renderers properly link in libGL now.
Acked-by: Brian Paul <[email protected]>
Diffstat (limited to 'src/hgl/GLView.cpp')
-rw-r--r-- | src/hgl/GLView.cpp | 643 |
1 files changed, 643 insertions, 0 deletions
diff --git a/src/hgl/GLView.cpp b/src/hgl/GLView.cpp new file mode 100644 index 00000000000..9ae5b5c83ac --- /dev/null +++ b/src/hgl/GLView.cpp @@ -0,0 +1,643 @@ +/* + * Copyright 2006-2012, Haiku. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Jérôme Duval, [email protected] + * Philippe Houdoin, [email protected] + * Stefano Ceccherini, [email protected] + */ + +#include <kernel/image.h> + +#include <GLView.h> + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <DirectWindow.h> +#include <GLRenderer.h> + +#include "interface/DirectWindowPrivate.h" +#include "GLDispatcher.h" +#include "GLRendererRoster.h" + + +struct glview_direct_info { + direct_buffer_info* direct_info; + bool direct_connected; + bool enable_direct_mode; + + glview_direct_info(); + ~glview_direct_info(); +}; + + +BGLView::BGLView(BRect rect, const char* name, ulong resizingMode, ulong mode, + ulong options) + : + BView(rect, name, B_FOLLOW_ALL_SIDES, mode | B_WILL_DRAW | B_FRAME_EVENTS), + // | B_FULL_UPDATE_ON_RESIZE) + fGc(NULL), + fOptions(options), + fDitherCount(0), + fDrawLock("BGLView draw lock"), + fDisplayLock("BGLView display lock"), + fClipInfo(NULL), + fRenderer(NULL), + fRoster(NULL), + fDitherMap(NULL) +{ + fRoster = new GLRendererRoster(this, options); +} + + +BGLView::~BGLView() +{ + delete fClipInfo; + if (fRenderer) + fRenderer->Release(); +} + + +void +BGLView::LockGL() +{ + // TODO: acquire the OpenGL API lock it on this glview + + fDisplayLock.Lock(); + if (fRenderer) + fRenderer->LockGL(); +} + + +void +BGLView::UnlockGL() +{ + if (fRenderer) + fRenderer->UnlockGL(); + fDisplayLock.Unlock(); + + // TODO: release the GL API lock to others glviews +} + + +void +BGLView::SwapBuffers() +{ + SwapBuffers(false); +} + + +void +BGLView::SwapBuffers(bool vSync) +{ + if (fRenderer) { + _LockDraw(); + fRenderer->SwapBuffers(vSync); + _UnlockDraw(); + } +} + + +BView* +BGLView::EmbeddedView() +{ + return NULL; +} + + +void* +BGLView::GetGLProcAddress(const char* procName) +{ + BGLDispatcher* glDispatcher = NULL; + + if (fRenderer) + glDispatcher = fRenderer->GLDispatcher(); + + if (glDispatcher) + return (void*)glDispatcher->AddressOf(procName); + + return NULL; +} + + +status_t +BGLView::CopyPixelsOut(BPoint source, BBitmap* dest) +{ + if (!fRenderer) + return B_ERROR; + + if (!dest || !dest->Bounds().IsValid()) + return B_BAD_VALUE; + + return fRenderer->CopyPixelsOut(source, dest); +} + + +status_t +BGLView::CopyPixelsIn(BBitmap* source, BPoint dest) +{ + if (!fRenderer) + return B_ERROR; + + if (!source || !source->Bounds().IsValid()) + return B_BAD_VALUE; + + return fRenderer->CopyPixelsIn(source, dest); +} + + +/*! Mesa's GLenum is not ulong but uint, so we can't use GLenum + without breaking this method signature. + Instead, we have to use the effective BeOS's SGI OpenGL GLenum type: + unsigned long. + */ +void +BGLView::ErrorCallback(unsigned long errorCode) +{ + char msg[32]; + sprintf(msg, "GL: Error code $%04lx.", errorCode); + // TODO: under BeOS R5, it call debugger(msg); + fprintf(stderr, "%s\n", msg); +} + + +void +BGLView::Draw(BRect updateRect) +{ + if (fRenderer) { + _LockDraw(); + fRenderer->Draw(updateRect); + _UnlockDraw(); + return; + } + // TODO: auto-size and center the string + MovePenTo(8, 32); + DrawString("No OpenGL renderer available!"); +} + + +void +BGLView::AttachedToWindow() +{ + BView::AttachedToWindow(); + + fBounds = Bounds(); + for (BView* view = this; view != NULL; view = view->Parent()) + view->ConvertToParent(&fBounds); + + fRenderer = fRoster->GetRenderer(); + if (fRenderer != NULL) { + // Jackburton: The following code was commented because it doesn't look + // good in "direct" mode: + // when the window is moved, the app_server doesn't paint the view's + // background, and the stuff behind the window itself shows up. + // Setting the view color to black, instead, looks a bit more elegant. +#if 0 + // Don't paint white window background when resized + SetViewColor(B_TRANSPARENT_32_BIT); +#else + SetViewColor(0, 0, 0); +#endif + + // Set default OpenGL viewport: + LockGL(); + glViewport(0, 0, Bounds().IntegerWidth(), Bounds().IntegerHeight()); + UnlockGL(); + fRenderer->FrameResized(Bounds().IntegerWidth(), + Bounds().IntegerHeight()); + + if (fClipInfo) { + fRenderer->DirectConnected(fClipInfo->direct_info); + fRenderer->EnableDirectMode(fClipInfo->enable_direct_mode); + } + + return; + } + + fprintf(stderr, "no renderer found! \n"); + + // No Renderer, no rendering. Setup a minimal "No Renderer" string drawing + // context + SetFont(be_bold_font); + // SetFontSize(16); +} + + +void +BGLView::AllAttached() +{ + BView::AllAttached(); +} + + +void +BGLView::DetachedFromWindow() +{ + if (fRenderer) + fRenderer->Release(); + fRenderer = NULL; + + BView::DetachedFromWindow(); +} + + +void +BGLView::AllDetached() +{ + BView::AllDetached(); +} + + +void +BGLView::FrameResized(float width, float height) +{ + fBounds = Bounds(); + for (BView* v = this; v; v = v->Parent()) + v->ConvertToParent(&fBounds); + + if (fRenderer) { + LockGL(); + _LockDraw(); + _CallDirectConnected(); + fRenderer->FrameResized(width, height); + _UnlockDraw(); + UnlockGL(); + } + + BView::FrameResized(width, height); +} + + +status_t +BGLView::Perform(perform_code d, void* arg) +{ + return BView::Perform(d, arg); +} + + +status_t +BGLView::Archive(BMessage* data, bool deep) const +{ + return BView::Archive(data, deep); +} + + +void +BGLView::MessageReceived(BMessage* msg) +{ + BView::MessageReceived(msg); +} + + +void +BGLView::SetResizingMode(uint32 mode) +{ + BView::SetResizingMode(mode); +} + + +void +BGLView::GetPreferredSize(float* _width, float* _height) +{ + if (_width) + *_width = 0; + if (_height) + *_height = 0; +} + + +void +BGLView::Show() +{ + BView::Show(); +} + + +void +BGLView::Hide() +{ + BView::Hide(); +} + + +BHandler* +BGLView::ResolveSpecifier(BMessage* msg, int32 index, BMessage* specifier, + int32 form, const char* property) +{ + return BView::ResolveSpecifier(msg, index, specifier, form, property); +} + + +status_t +BGLView::GetSupportedSuites(BMessage* data) +{ + return BView::GetSupportedSuites(data); +} + + +void +BGLView::DirectConnected(direct_buffer_info* info) +{ + if (fClipInfo == NULL) { + fClipInfo = new (std::nothrow) glview_direct_info(); + if (fClipInfo == NULL) + return; + } + + direct_buffer_info* localInfo = fClipInfo->direct_info; + + switch (info->buffer_state & B_DIRECT_MODE_MASK) { + case B_DIRECT_START: + fClipInfo->direct_connected = true; + memcpy(localInfo, info, DIRECT_BUFFER_INFO_AREA_SIZE); + _UnlockDraw(); + break; + + case B_DIRECT_MODIFY: + _LockDraw(); + memcpy(localInfo, info, DIRECT_BUFFER_INFO_AREA_SIZE); + _UnlockDraw(); + break; + + case B_DIRECT_STOP: + fClipInfo->direct_connected = false; + _LockDraw(); + break; + } + + if (fRenderer) + _CallDirectConnected(); +} + + +void +BGLView::EnableDirectMode(bool enabled) +{ + if (fRenderer) + fRenderer->EnableDirectMode(enabled); + if (fClipInfo == NULL) { + fClipInfo = new (std::nothrow) glview_direct_info(); + if (fClipInfo == NULL) + return; + } + + fClipInfo->enable_direct_mode = enabled; +} + + +void +BGLView::_LockDraw() +{ + if (!fClipInfo || !fClipInfo->enable_direct_mode) + return; + + fDrawLock.Lock(); +} + + +void +BGLView::_UnlockDraw() +{ + if (!fClipInfo || !fClipInfo->enable_direct_mode) + return; + + fDrawLock.Unlock(); +} + + +void +BGLView::_CallDirectConnected() +{ + if (!fClipInfo) + return; + + direct_buffer_info* localInfo = fClipInfo->direct_info; + direct_buffer_info* info = (direct_buffer_info*)malloc( + DIRECT_BUFFER_INFO_AREA_SIZE); + if (info == NULL) + return; + + memcpy(info, localInfo, DIRECT_BUFFER_INFO_AREA_SIZE); + + // Collect the rects into a BRegion, then clip to the view's bounds + BRegion region; + for (uint32 c = 0; c < localInfo->clip_list_count; c++) + region.Include(localInfo->clip_list[c]); + BRegion boundsRegion = fBounds.OffsetByCopy(localInfo->window_bounds.left, + localInfo->window_bounds.top); + info->window_bounds = boundsRegion.RectAtInt(0); + // window_bounds are now view bounds + region.IntersectWith(&boundsRegion); + + info->clip_list_count = region.CountRects(); + info->clip_bounds = region.FrameInt(); + + for (uint32 c = 0; c < info->clip_list_count; c++) + info->clip_list[c] = region.RectAtInt(c); + fRenderer->DirectConnected(info); + free(info); +} + + +//---- virtual reserved methods ---------- + + +void BGLView::_ReservedGLView1() {} +void BGLView::_ReservedGLView2() {} +void BGLView::_ReservedGLView3() {} +void BGLView::_ReservedGLView4() {} +void BGLView::_ReservedGLView5() {} +void BGLView::_ReservedGLView6() {} +void BGLView::_ReservedGLView7() {} +void BGLView::_ReservedGLView8() {} + + +// #pragma mark - + + +// BeOS compatibility: contrary to others BView's contructors, +// BGLView one wants a non-const name argument. +BGLView::BGLView(BRect rect, char* name, ulong resizingMode, ulong mode, + ulong options) + : + BView(rect, name, B_FOLLOW_ALL_SIDES, mode | B_WILL_DRAW | B_FRAME_EVENTS), + fGc(NULL), + fOptions(options), + fDitherCount(0), + fDrawLock("BGLView draw lock"), + fDisplayLock("BGLView display lock"), + fClipInfo(NULL), + fRenderer(NULL), + fRoster(NULL), + fDitherMap(NULL) +{ + fRoster = new GLRendererRoster(this, options); +} + + +#if 0 +// TODO: implement BGLScreen class... + + +BGLScreen::BGLScreen(char* name, ulong screenMode, ulong options, + status_t* error, bool debug) + : + BWindowScreen(name, screenMode, error, debug) +{ +} + + +BGLScreen::~BGLScreen() +{ +} + + +void +BGLScreen::LockGL() +{ +} + + +void +BGLScreen::UnlockGL() +{ +} + + +void +BGLScreen::SwapBuffers() +{ +} + + +void +BGLScreen::ErrorCallback(unsigned long errorCode) +{ + // Mesa's GLenum is not ulong but uint! + char msg[32]; + sprintf(msg, "GL: Error code $%04lx.", errorCode); + // debugger(msg); + fprintf(stderr, "%s\n", msg); + return; +} + + +void +BGLScreen::ScreenConnected(bool enabled) +{ +} + + +void +BGLScreen::FrameResized(float width, float height) +{ + return BWindowScreen::FrameResized(width, height); +} + + +status_t +BGLScreen::Perform(perform_code d, void* arg) +{ + return BWindowScreen::Perform(d, arg); +} + + +status_t +BGLScreen::Archive(BMessage* data, bool deep) const +{ + return BWindowScreen::Archive(data, deep); +} + + +void +BGLScreen::MessageReceived(BMessage* msg) +{ + BWindowScreen::MessageReceived(msg); +} + + +void +BGLScreen::Show() +{ + BWindowScreen::Show(); +} + + +void +BGLScreen::Hide() +{ + BWindowScreen::Hide(); +} + + +BHandler* +BGLScreen::ResolveSpecifier(BMessage* msg, int32 index, BMessage* specifier, + int32 form, const char* property) +{ + return BWindowScreen::ResolveSpecifier(msg, index, specifier, + form, property); +} + + +status_t +BGLScreen::GetSupportedSuites(BMessage* data) +{ + return BWindowScreen::GetSupportedSuites(data); +} + + +//---- virtual reserved methods ---------- + +void BGLScreen::_ReservedGLScreen1() {} +void BGLScreen::_ReservedGLScreen2() {} +void BGLScreen::_ReservedGLScreen3() {} +void BGLScreen::_ReservedGLScreen4() {} +void BGLScreen::_ReservedGLScreen5() {} +void BGLScreen::_ReservedGLScreen6() {} +void BGLScreen::_ReservedGLScreen7() {} +void BGLScreen::_ReservedGLScreen8() {} +#endif + + +const char* color_space_name(color_space space) +{ +#define C2N(a) case a: return #a + + switch (space) { + C2N(B_RGB24); + C2N(B_RGB32); + C2N(B_RGBA32); + C2N(B_RGB32_BIG); + C2N(B_RGBA32_BIG); + C2N(B_GRAY8); + C2N(B_GRAY1); + C2N(B_RGB16); + C2N(B_RGB15); + C2N(B_RGBA15); + C2N(B_CMAP8); + default: + return "Unknown!"; + }; + +#undef C2N +}; + + +glview_direct_info::glview_direct_info() +{ + // TODO: See direct_window_data() in app_server's ServerWindow.cpp + direct_info = (direct_buffer_info*)calloc(1, DIRECT_BUFFER_INFO_AREA_SIZE); + direct_connected = false; + enable_direct_mode = false; +} + + +glview_direct_info::~glview_direct_info() +{ + free(direct_info); +} + |