* DirectConnect() with B_DIRECT_START must not unlock drawing before updating

to the latest direct_buffer_info - it could trash memory before.
* Now handles failed allocations more gracefully.
* Cleanup.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32719 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2009-08-26 17:24:15 +00:00
parent 8cc8b1b7e9
commit 4c72b8cf43
+106 -77
View File
@@ -1,5 +1,5 @@
/* /*
* Copyright 2006-2008, Haiku. All rights reserved. * Copyright 2006-2009, Haiku. All rights reserved.
* Distributed under the terms of the MIT License. * Distributed under the terms of the MIT License.
* *
* Authors: * Authors:
@@ -11,19 +11,19 @@
/* /*
* Mesa 3-D graphics library * Mesa 3-D graphics library
* Version: 6.1 * Version: 6.1
* *
* Copyright (C) 1999-2004 Brian Paul All Rights Reserved. * Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
* *
* Permission is hereby granted, free of charge, to any person obtaining a * Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"), * copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation * to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense, * the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the * and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions: * Software is furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included * The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software. * in all copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
@@ -49,7 +49,7 @@ struct glview_direct_info {
direct_buffer_info *direct_info; direct_buffer_info *direct_info;
bool direct_connected; bool direct_connected;
bool enable_direct_mode; bool enable_direct_mode;
glview_direct_info(); glview_direct_info();
~glview_direct_info(); ~glview_direct_info();
}; };
@@ -57,16 +57,18 @@ struct glview_direct_info {
BGLView::BGLView(BRect rect, char* name, ulong resizingMode, ulong mode, BGLView::BGLView(BRect rect, char* name, ulong resizingMode, ulong mode,
ulong options) ulong options)
: BView(rect, name, B_FOLLOW_ALL_SIDES, mode | B_WILL_DRAW | B_FRAME_EVENTS), // | B_FULL_UPDATE_ON_RESIZE) :
BView(rect, name, B_FOLLOW_ALL_SIDES, mode | B_WILL_DRAW | B_FRAME_EVENTS),
// | B_FULL_UPDATE_ON_RESIZE)
fGc(NULL), fGc(NULL),
fOptions(options), fOptions(options),
fDitherCount(0), fDitherCount(0),
fDrawLock("BGLView draw lock"), fDrawLock("BGLView draw lock"),
fDisplayLock("BGLView display lock"), fDisplayLock("BGLView display lock"),
fClipInfo(NULL), fClipInfo(NULL),
fRenderer(NULL), fRenderer(NULL),
fRoster(NULL), fRoster(NULL),
fDitherMap(NULL) fDitherMap(NULL)
{ {
fRoster = new GLRendererRoster(this, options); fRoster = new GLRendererRoster(this, options);
} }
@@ -97,7 +99,7 @@ BGLView::UnlockGL()
if (fRenderer) if (fRenderer)
fRenderer->UnlockGL(); fRenderer->UnlockGL();
fDisplayLock.Unlock(); fDisplayLock.Unlock();
// TODO: release the GL API lock to others glviews // TODO: release the GL API lock to others glviews
} }
@@ -132,7 +134,7 @@ BGLView::CopyPixelsOut(BPoint source, BBitmap *dest)
{ {
if (!fRenderer) if (!fRenderer)
return B_ERROR; return B_ERROR;
if (!dest || !dest->Bounds().IsValid()) if (!dest || !dest->Bounds().IsValid())
return B_BAD_VALUE; return B_BAD_VALUE;
@@ -145,7 +147,7 @@ BGLView::CopyPixelsIn(BBitmap *source, BPoint dest)
{ {
if (!fRenderer) if (!fRenderer)
return B_ERROR; return B_ERROR;
if (!source || !source->Bounds().IsValid()) if (!source || !source->Bounds().IsValid())
return B_BAD_VALUE; return B_BAD_VALUE;
@@ -159,7 +161,7 @@ BGLView::CopyPixelsIn(BBitmap *source, BPoint dest)
unsigned long. unsigned long.
*/ */
void void
BGLView::ErrorCallback(unsigned long errorCode) BGLView::ErrorCallback(unsigned long errorCode)
{ {
char msg[32]; char msg[32];
sprintf(msg, "GL: Error code $%04lx.", errorCode); sprintf(msg, "GL: Error code $%04lx.", errorCode);
@@ -172,10 +174,10 @@ void
BGLView::Draw(BRect updateRect) BGLView::Draw(BRect updateRect)
{ {
if (fRenderer) { if (fRenderer) {
_LockDraw(); _LockDraw();
fRenderer->Draw(updateRect); fRenderer->Draw(updateRect);
_UnlockDraw(); _UnlockDraw();
return; return;
} }
// TODO: auto-size and center the string // TODO: auto-size and center the string
MovePenTo(8, 32); MovePenTo(8, 32);
@@ -197,7 +199,7 @@ BGLView::AttachedToWindow()
// Jackburton: The following code was commented because it doesn't look // Jackburton: The following code was commented because it doesn't look
// good in "direct" mode: // good in "direct" mode:
// when the window is moved, the app_server doesn't paint the view's // when the window is moved, the app_server doesn't paint the view's
// background, and the stuff behind the window itself shows up. // background, and the stuff behind the window itself shows up.
// Setting the view color to black, instead, looks a bit more elegant. // Setting the view color to black, instead, looks a bit more elegant.
#if 0 #if 0
// Don't paint white window background when resized // Don't paint white window background when resized
@@ -207,7 +209,8 @@ BGLView::AttachedToWindow()
#endif #endif
// Set default OpenGL viewport: // Set default OpenGL viewport:
glViewport(0, 0, Bounds().IntegerWidth(), Bounds().IntegerHeight()); glViewport(0, 0, Bounds().IntegerWidth(), Bounds().IntegerHeight());
fRenderer->FrameResized(Bounds().IntegerWidth(), Bounds().IntegerHeight()); fRenderer->FrameResized(Bounds().IntegerWidth(),
Bounds().IntegerHeight());
if (fClipInfo) { if (fClipInfo) {
fRenderer->DirectConnected( fRenderer->DirectConnected(
@@ -218,7 +221,7 @@ BGLView::AttachedToWindow()
return; return;
} }
fprintf(stderr, "no renderer found! \n"); fprintf(stderr, "no renderer found! \n");
// No Renderer, no rendering. Setup a minimal "No Renderer" string drawing // No Renderer, no rendering. Setup a minimal "No Renderer" string drawing
@@ -234,7 +237,7 @@ BGLView::AllAttached()
BView::AllAttached(); BView::AllAttached();
} }
void void
BGLView::DetachedFromWindow() BGLView::DetachedFromWindow()
{ {
@@ -316,9 +319,8 @@ BGLView::Hide()
BHandler * BHandler *
BGLView::ResolveSpecifier(BMessage *msg, int32 index, BGLView::ResolveSpecifier(BMessage *msg, int32 index, BMessage *specifier,
BMessage *specifier, int32 form, int32 form, const char *property)
const char *property)
{ {
return BView::ResolveSpecifier(msg, index, specifier, form, property); return BView::ResolveSpecifier(msg, index, specifier, form, property);
} }
@@ -334,29 +336,33 @@ BGLView::GetSupportedSuites(BMessage *data)
void void
BGLView::DirectConnected(direct_buffer_info *info) BGLView::DirectConnected(direct_buffer_info *info)
{ {
if (!fClipInfo/* && m_direct_connection_disabled*/) { if (fClipInfo == NULL) {
fClipInfo = new glview_direct_info(); fClipInfo = new(std::nothrow) glview_direct_info();
if (fClipInfo == NULL)
return;
} }
glview_direct_info *glviewDirectInfo = (glview_direct_info *)fClipInfo; glview_direct_info *glviewDirectInfo = (glview_direct_info *)fClipInfo;
direct_buffer_info *localInfo = glviewDirectInfo->direct_info; direct_buffer_info *localInfo = glviewDirectInfo->direct_info;
switch(info->buffer_state & B_DIRECT_MODE_MASK) { switch (info->buffer_state & B_DIRECT_MODE_MASK) {
case B_DIRECT_START: case B_DIRECT_START:
glviewDirectInfo->direct_connected = true; glviewDirectInfo->direct_connected = true;
_UnlockDraw();
case B_DIRECT_MODIFY:
{
_LockDraw();
memcpy(localInfo, info, DIRECT_BUFFER_INFO_AREA_SIZE); memcpy(localInfo, info, DIRECT_BUFFER_INFO_AREA_SIZE);
_UnlockDraw(); _UnlockDraw();
break; break;
}
case B_DIRECT_STOP: case B_DIRECT_MODIFY:
_LockDraw();
memcpy(localInfo, info, DIRECT_BUFFER_INFO_AREA_SIZE);
_UnlockDraw();
break;
case B_DIRECT_STOP:
glviewDirectInfo->direct_connected = false; glviewDirectInfo->direct_connected = false;
_LockDraw(); _LockDraw();
break; break;
} }
if (fRenderer) if (fRenderer)
_CallDirectConnected(); _CallDirectConnected();
@@ -368,9 +374,12 @@ BGLView::EnableDirectMode(bool enabled)
{ {
if (fRenderer) if (fRenderer)
fRenderer->EnableDirectMode(enabled); fRenderer->EnableDirectMode(enabled);
if (!fClipInfo) { if (fClipInfo == NULL) {
fClipInfo = new glview_direct_info(); fClipInfo = new(std::nothrow) glview_direct_info();
if (fClipInfo == NULL)
return;
} }
((glview_direct_info *)fClipInfo)->enable_direct_mode = enabled; ((glview_direct_info *)fClipInfo)->enable_direct_mode = enabled;
} }
@@ -394,7 +403,7 @@ BGLView::_UnlockDraw()
if (!info || !info->enable_direct_mode) if (!info || !info->enable_direct_mode)
return; return;
fDrawLock.Unlock(); fDrawLock.Unlock();
} }
@@ -404,23 +413,29 @@ BGLView::_CallDirectConnected()
{ {
if (!fClipInfo) if (!fClipInfo)
return; return;
glview_direct_info *glviewDirectInfo = (glview_direct_info *)fClipInfo; glview_direct_info *glviewDirectInfo = (glview_direct_info *)fClipInfo;
direct_buffer_info *localInfo = glviewDirectInfo->direct_info; direct_buffer_info *localInfo = glviewDirectInfo->direct_info;
direct_buffer_info *info = (direct_buffer_info *)calloc(1, DIRECT_BUFFER_INFO_AREA_SIZE); direct_buffer_info *info = (direct_buffer_info *)calloc(1,
DIRECT_BUFFER_INFO_AREA_SIZE);
if (info == NULL)
return;
memcpy(info, localInfo, DIRECT_BUFFER_INFO_AREA_SIZE); memcpy(info, localInfo, DIRECT_BUFFER_INFO_AREA_SIZE);
// Collect the rects into a BRegion, then clip to the view's bounds // Collect the rects into a BRegion, then clip to the view's bounds
BRegion region; BRegion region;
for (uint32 c = 0; c < localInfo->clip_list_count; c++) for (uint32 c = 0; c < localInfo->clip_list_count; c++)
region.Include(localInfo->clip_list[c]); region.Include(localInfo->clip_list[c]);
BRegion boundsRegion = fBounds.OffsetByCopy(localInfo->window_bounds.left, localInfo->window_bounds.top); BRegion boundsRegion = fBounds.OffsetByCopy(localInfo->window_bounds.left,
info->window_bounds = boundsRegion.RectAtInt(0); // window_bounds are now view bounds localInfo->window_bounds.top);
info->window_bounds = boundsRegion.RectAtInt(0);
// window_bounds are now view bounds
region.IntersectWith(&boundsRegion); region.IntersectWith(&boundsRegion);
info->clip_list_count = region.CountRects(); info->clip_list_count = region.CountRects();
info->clip_bounds = region.FrameInt(); info->clip_bounds = region.FrameInt();
for (uint32 c = 0; c < info->clip_list_count; c++) for (uint32 c = 0; c < info->clip_list_count; c++)
info->clip_list[c] = region.RectAtInt(c); info->clip_list[c] = region.RectAtInt(c);
fRenderer->DirectConnected(info); fRenderer->DirectConnected(info);
@@ -430,6 +445,7 @@ BGLView::_CallDirectConnected()
//---- virtual reserved methods ---------- //---- virtual reserved methods ----------
void BGLView::_ReservedGLView1() {} void BGLView::_ReservedGLView1() {}
void BGLView::_ReservedGLView2() {} void BGLView::_ReservedGLView2() {}
void BGLView::_ReservedGLView3() {} void BGLView::_ReservedGLView3() {}
@@ -439,53 +455,51 @@ void BGLView::_ReservedGLView6() {}
void BGLView::_ReservedGLView7() {} void BGLView::_ReservedGLView7() {}
void BGLView::_ReservedGLView8() {} void BGLView::_ReservedGLView8() {}
#if 0
// Not implemented!!!
BGLView::BGLView(const BGLView &v)
: BView(v)
{
// XXX not sure how this should work
printf("Warning BGLView::copy constructor not implemented\n");
}
BGLView &BGLView::operator=(const BGLView &v)
{
printf("Warning BGLView::operator= not implemented\n");
return *this;
}
#endif
// #pragma mark - // #pragma mark -
#if 0 #if 0
// TODO: implement BGLScreen class... // TODO: implement BGLScreen class...
BGLScreen::BGLScreen(char* name, ulong screenMode, ulong options, BGLScreen::BGLScreen(char* name, ulong screenMode, ulong options,
status_t *error, bool debug) status_t *error, bool debug)
: BWindowScreen(name, screenMode, error, debug) :
BWindowScreen(name, screenMode, error, debug)
{ {
} }
BGLScreen::~BGLScreen() BGLScreen::~BGLScreen()
{ {
} }
void BGLScreen::LockGL()
void
BGLScreen::LockGL()
{ {
} }
void BGLScreen::UnlockGL()
void
BGLScreen::UnlockGL()
{ {
} }
void BGLScreen::SwapBuffers()
void
BGLScreen::SwapBuffers()
{ {
} }
void BGLScreen::ErrorCallback(unsigned long errorCode) // Mesa's GLenum is not ulong but uint!
void
BGLScreen::ErrorCallback(unsigned long errorCode)
{ {
// Mesa's GLenum is not ulong but uint!
char msg[32]; char msg[32];
sprintf(msg, "GL: Error code $%04lx.", errorCode); sprintf(msg, "GL: Error code $%04lx.", errorCode);
// debugger(msg); // debugger(msg);
@@ -493,50 +507,65 @@ void BGLScreen::ErrorCallback(unsigned long errorCode) // Mesa's GLenum is not u
return; return;
} }
void BGLScreen::ScreenConnected(bool enabled)
void
BGLScreen::ScreenConnected(bool enabled)
{ {
} }
void BGLScreen::FrameResized(float width, float height) void
BGLScreen::FrameResized(float width, float height)
{ {
return BWindowScreen::FrameResized(width, height); return BWindowScreen::FrameResized(width, height);
} }
status_t BGLScreen::Perform(perform_code d, void *arg)
status_t
BGLScreen::Perform(perform_code d, void *arg)
{ {
return BWindowScreen::Perform(d, arg); return BWindowScreen::Perform(d, arg);
} }
status_t BGLScreen::Archive(BMessage *data, bool deep) const status_t
BGLScreen::Archive(BMessage *data, bool deep) const
{ {
return BWindowScreen::Archive(data, deep); return BWindowScreen::Archive(data, deep);
} }
void BGLScreen::MessageReceived(BMessage *msg)
void
BGLScreen::MessageReceived(BMessage *msg)
{ {
BWindowScreen::MessageReceived(msg); BWindowScreen::MessageReceived(msg);
} }
void BGLScreen::Show()
void
BGLScreen::Show()
{ {
BWindowScreen::Show(); BWindowScreen::Show();
} }
void BGLScreen::Hide()
void
BGLScreen::Hide()
{ {
BWindowScreen::Hide(); BWindowScreen::Hide();
} }
BHandler *BGLScreen::ResolveSpecifier(BMessage *msg, int32 index,
BMessage *specifier, int32 form, BHandler *
const char *property) BGLScreen::ResolveSpecifier(BMessage *msg, int32 index, BMessage *specifier,
int32 form, const char *property)
{ {
return BWindowScreen::ResolveSpecifier(msg, index, specifier, form, property); return BWindowScreen::ResolveSpecifier(msg, index, specifier, form, property);
} }
status_t BGLScreen::GetSupportedSuites(BMessage *data)
status_t
BGLScreen::GetSupportedSuites(BMessage *data)
{ {
return BWindowScreen::GetSupportedSuites(data); return BWindowScreen::GetSupportedSuites(data);
} }