assdraw: fix assertion failure from reading and writing a bitmap at the same time

Originally committed to SVN as r6860.
This commit is contained in:
Thomas Goyne 2012-05-24 01:56:12 +00:00
parent f0eaaacd06
commit 01eba350b7

View file

@ -6,63 +6,64 @@
#include <wx/dcclient.h> #include <wx/dcclient.h>
namespace GUI { namespace GUI {
BEGIN_EVENT_TABLE(AGGWindow, wxWindow) BEGIN_EVENT_TABLE(AGGWindow, wxWindow)
EVT_PAINT(AGGWindow::onPaint) EVT_PAINT(AGGWindow::onPaint)
EVT_SIZE(AGGWindow::onSize) EVT_SIZE(AGGWindow::onSize)
EVT_ERASE_BACKGROUND(AGGWindow::onEraseBackground) EVT_ERASE_BACKGROUND(AGGWindow::onEraseBackground)
END_EVENT_TABLE() END_EVENT_TABLE()
AGGWindow::AGGWindow(wxWindow* parent, wxWindowID id, AGGWindow::AGGWindow(wxWindow* parent, wxWindowID id,
const wxPoint& pos, const wxSize& size, long style): const wxPoint& pos, const wxSize& size, long style):
wxWindow(parent, id, pos, size, style, wxT("AGGWindow")), wxWindow(parent, id, pos, size, style, wxT("AGGWindow")),
bitmap(NULL) { bitmap(NULL) {
} }
void AGGWindow::init(const int width, const int height) { void AGGWindow::init(const int width, const int height) {
memDC.SelectObject(wxNullBitmap); memDC.SelectObject(wxNullBitmap);
delete bitmap; delete bitmap;
int ncheight = height, ncwidth = width; int ncheight = height, ncwidth = width;
if (ncwidth < 1) ncwidth = 1; if (ncwidth < 1) ncwidth = 1;
if (ncheight < 1) ncheight = 1; if (ncheight < 1) ncheight = 1;
bitmap = new wxBitmap(ncwidth, ncheight, PixelFormat::wxWidgetsType::BitsPerPixel); bitmap = new wxBitmap(ncwidth, ncheight, PixelFormat::wxWidgetsType::BitsPerPixel);
memDC.SelectObject(*bitmap);
// Draw the bitmap // Draw the bitmap
attachAndDraw(); attachAndDraw();
memDC.SelectObject(*bitmap);
// Request a full redraw of the window // Request a full redraw of the window
Refresh(false); Refresh(false);
} }
AGGWindow::~AGGWindow() { AGGWindow::~AGGWindow() {
memDC.SelectObject(wxNullBitmap); memDC.SelectObject(wxNullBitmap);
delete bitmap; delete bitmap;
} }
void AGGWindow::attachAndDraw() { void AGGWindow::attachAndDraw() {
// Get raw access to the wxWidgets bitmap -- this locks the pixels and // Get raw access to the wxWidgets bitmap -- this locks the pixels and
// unlocks on destruction. // unlocks on destruction.
PixelData data(*bitmap); PixelData data(*bitmap);
assert(data); assert(data);
#if 1 #if 1
// This cast looks like it is ignoring byte-ordering, but the // This cast looks like it is ignoring byte-ordering, but the
// pixel format already explicitly handles that. // pixel format already explicitly handles that.
assert(data.GetPixels().IsOk()); assert(data.GetPixels().IsOk());
wxAlphaPixelFormat::ChannelType* pd = (wxAlphaPixelFormat::ChannelType*) &data.GetPixels().Data(); wxAlphaPixelFormat::ChannelType* pd = (wxAlphaPixelFormat::ChannelType*) &data.GetPixels().Data();
// wxWidgets always returns a pointer to the first row of pixels, whether // wxWidgets always returns a pointer to the first row of pixels, whether
// that is stored at the beginning of the buffer (stride > 0) or at the // that is stored at the beginning of the buffer (stride > 0) or at the
// end of the buffer (stride < 0). AGG always wants a pointer to the // end of the buffer (stride < 0). AGG always wants a pointer to the
// beginning of the buffer, no matter what the stride. (AGG does handle // beginning of the buffer, no matter what the stride. (AGG does handle
// negative strides correctly.) // negative strides correctly.)
// Upshot: if the stride is negative, rewind the pointer from the end of // Upshot: if the stride is negative, rewind the pointer from the end of
// the buffer to the beginning. // the buffer to the beginning.
const int stride = data.GetRowStride(); const int stride = data.GetRowStride();
if (stride < 0) if (stride < 0)
pd += (data.GetHeight() - 1) * stride; pd += (data.GetHeight() - 1) * stride;
rBuf.attach(pd, data.GetWidth(), data.GetHeight(), stride); rBuf.attach(pd, data.GetWidth(), data.GetHeight(), stride);
@ -91,23 +92,23 @@ namespace GUI {
} }
#endif #endif
} }
void AGGWindow::onSize(wxSizeEvent& event) { void AGGWindow::onSize(wxSizeEvent& event) {
const wxSize size = GetClientSize(); const wxSize size = GetClientSize();
if (bitmap && size.GetWidth() == bitmap->GetWidth() && size.GetHeight() == bitmap->GetHeight()) if (bitmap && size.GetWidth() == bitmap->GetWidth() && size.GetHeight() == bitmap->GetHeight())
return; return;
init(size.GetWidth(), size.GetHeight()); init(size.GetWidth(), size.GetHeight());
} }
void AGGWindow::onPaint(wxPaintEvent& event) { void AGGWindow::onPaint(wxPaintEvent& event) {
wxPaintDC dc(this); wxPaintDC dc(this);
wxCoord width, height; wxCoord width, height;
dc.GetSize(&width, &height); dc.GetSize(&width, &height);
if (!bitmap || bitmap->GetWidth() != width || bitmap->GetHeight() != height) if (!bitmap || bitmap->GetWidth() != width || bitmap->GetHeight() != height)
init(width, height); init(width, height);
// Iterate over regions needing repainting // Iterate over regions needing repainting
wxRegionIterator regions(GetUpdateRegion()); wxRegionIterator regions(GetUpdateRegion());
wxRect rect; wxRect rect;