From dc4c7cc492fd225a18f0d5af5b7dea0f8e791aba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Mon, 27 Apr 2009 20:28:11 +0000 Subject: [PATCH] * honors new frame size in the LockGL() method of the renderer, FrameResized() now notifies the renderer. * checks whether the rendered bitmap size matches the direct info size, if not, the renderer doesn't draw. * we don't lock the view looper anymore in LockGL(), this avoids deadlocks with FrameResized(). * lock drawing when modifying the direct connection info. * the renderer now locks the view looper with a timeout, as on resize the looper is locked and FrameResized called. * the bug #3027 is fixed. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30472 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../MesaSoftwareRenderer.cpp | 244 ++++++++++-------- .../MesaSoftwareRenderer.h | 9 +- src/kits/opengl/GLView.cpp | 23 +- 3 files changed, 160 insertions(+), 116 deletions(-) diff --git a/src/add-ons/opengl/mesa_software_renderer/MesaSoftwareRenderer.cpp b/src/add-ons/opengl/mesa_software_renderer/MesaSoftwareRenderer.cpp index 54e1eb4d32..eeae5d274c 100644 --- a/src/add-ons/opengl/mesa_software_renderer/MesaSoftwareRenderer.cpp +++ b/src/add-ons/opengl/mesa_software_renderer/MesaSoftwareRenderer.cpp @@ -297,7 +297,13 @@ MesaSoftwareRenderer::MesaSoftwareRenderer(BGLView* view, ulong options, _mesa_enable_1_3_extensions(fContext); _mesa_enable_1_4_extensions(fContext); _mesa_enable_1_5_extensions(fContext); + _mesa_enable_2_0_extensions(fContext); + _mesa_enable_2_1_extensions(fContext); + BRect bounds = view->Bounds(); + fWidth = fNewWidth = (GLint)bounds.Width(); + fHeight = fNewHeight = (GLint)bounds.Height(); + // some stupid applications (Quake2) don't even think about calling LockGL() // before using glGetString and its glGet*() friends... // so make sure there is at least a valid context. @@ -326,93 +332,89 @@ MesaSoftwareRenderer::LockGL() _mesa_make_current(fContext, fFrameBuffer, fFrameBuffer); - BRect b = GLView()->Bounds(); color_space cs = B_RGBA32; + BAutolock lock(fInfoLocker); if (fDirectModeEnabled && fInfo != NULL) { cs = BScreen(GLView()->Window()).ColorSpace(); + fNewWidth = fInfo->window_bounds.right + - fInfo->window_bounds.left + 1; + fNewHeight = fInfo->window_bounds.bottom + - fInfo->window_bounds.top + 1; } - uint32 width = b.IntegerWidth() + 1; - uint32 height = b.IntegerHeight() + 1; - if (width != fWidth || height != fHeight || !fBitmap || cs != fColorSpace) { - if (cs != fColorSpace) { - switch (cs) { - case B_RGBA32: - fRenderBuffer->GetRow = get_row_RGBA32; - fRenderBuffer->GetValues = get_values_RGBA32; - fRenderBuffer->PutRow = put_row_RGBA32; - fRenderBuffer->PutRowRGB = put_row_rgb_RGBA32; - fRenderBuffer->PutMonoRow = put_mono_row_RGBA32; - fRenderBuffer->PutValues = put_values_RGBA32; - fRenderBuffer->PutMonoValues = put_mono_values_RGBA32; - break; - case B_RGB32: - fRenderBuffer->GetRow = get_row_RGB32; - fRenderBuffer->GetValues = get_values_RGB32; - fRenderBuffer->PutRow = put_row_RGB32; - fRenderBuffer->PutRowRGB = put_row_rgb_RGB32; - fRenderBuffer->PutMonoRow = put_mono_row_RGB32; - fRenderBuffer->PutValues = put_values_RGB32; - fRenderBuffer->PutMonoValues = put_mono_values_RGB32; - break; - case B_RGB24: - fRenderBuffer->GetRow = get_row_RGB24; - fRenderBuffer->GetValues = get_values_RGB24; - fRenderBuffer->PutRow = put_row_RGB24; - fRenderBuffer->PutRowRGB = put_row_rgb_RGB24; - fRenderBuffer->PutMonoRow = put_mono_row_RGB24; - fRenderBuffer->PutValues = put_values_RGB24; - fRenderBuffer->PutMonoValues = put_mono_values_RGB24; - break; - case B_RGB16: - fRenderBuffer->GetRow = get_row_RGB16; - fRenderBuffer->GetValues = get_values_RGB16; - fRenderBuffer->PutRow = put_row_RGB16; - fRenderBuffer->PutRowRGB = put_row_rgb_RGB16; - fRenderBuffer->PutMonoRow = put_mono_row_RGB16; - fRenderBuffer->PutValues = put_values_RGB16; - fRenderBuffer->PutMonoValues = put_mono_values_RGB16; - break; - case B_RGB15: - fRenderBuffer->GetRow = get_row_RGB15; - fRenderBuffer->GetValues = get_values_RGB15; - fRenderBuffer->PutRow = put_row_RGB15; - fRenderBuffer->PutRowRGB = put_row_rgb_RGB15; - fRenderBuffer->PutMonoRow = put_mono_row_RGB15; - fRenderBuffer->PutValues = put_values_RGB15; - fRenderBuffer->PutMonoValues = put_mono_values_RGB15; - break; - case B_CMAP8: - fRenderBuffer->GetRow = get_row_CMAP8; - fRenderBuffer->GetValues = get_values_CMAP8; - fRenderBuffer->PutRow = put_row_CMAP8; - fRenderBuffer->PutRowRGB = put_row_rgb_CMAP8; - fRenderBuffer->PutMonoRow = put_mono_row_CMAP8; - fRenderBuffer->PutValues = put_values_CMAP8; - fRenderBuffer->PutMonoValues = put_mono_values_CMAP8; - break; - default: - fprintf(stderr, "unsupported screen color space %d\n", cs); - debugger("unsupported OpenGL color space"); - break; - } - } - // allocate new size of back buffer bitmap - delete fBitmap; + if (fBitmap && cs == fColorSpace && fNewWidth == fWidth + && fNewHeight == fHeight) + return; + + if (cs != fColorSpace) { fColorSpace = cs; - BRect rect(0.0, 0.0, width - 1, height - 1); - fBitmap = new BBitmap(rect, fColorSpace); - for (uint i = 0; i < height; i++) { - fRowAddr[height - i - 1] = (GLvoid *)((GLubyte *)fBitmap->Bits() - + i * fBitmap->BytesPerRow()); + switch (fColorSpace) { + case B_RGBA32: + fRenderBuffer->GetRow = get_row_RGBA32; + fRenderBuffer->GetValues = get_values_RGBA32; + fRenderBuffer->PutRow = put_row_RGBA32; + fRenderBuffer->PutRowRGB = put_row_rgb_RGBA32; + fRenderBuffer->PutMonoRow = put_mono_row_RGBA32; + fRenderBuffer->PutValues = put_values_RGBA32; + fRenderBuffer->PutMonoValues = put_mono_values_RGBA32; + break; + case B_RGB32: + fRenderBuffer->GetRow = get_row_RGB32; + fRenderBuffer->GetValues = get_values_RGB32; + fRenderBuffer->PutRow = put_row_RGB32; + fRenderBuffer->PutRowRGB = put_row_rgb_RGB32; + fRenderBuffer->PutMonoRow = put_mono_row_RGB32; + fRenderBuffer->PutValues = put_values_RGB32; + fRenderBuffer->PutMonoValues = put_mono_values_RGB32; + break; + case B_RGB24: + fRenderBuffer->GetRow = get_row_RGB24; + fRenderBuffer->GetValues = get_values_RGB24; + fRenderBuffer->PutRow = put_row_RGB24; + fRenderBuffer->PutRowRGB = put_row_rgb_RGB24; + fRenderBuffer->PutMonoRow = put_mono_row_RGB24; + fRenderBuffer->PutValues = put_values_RGB24; + fRenderBuffer->PutMonoValues = put_mono_values_RGB24; + break; + case B_RGB16: + fRenderBuffer->GetRow = get_row_RGB16; + fRenderBuffer->GetValues = get_values_RGB16; + fRenderBuffer->PutRow = put_row_RGB16; + fRenderBuffer->PutRowRGB = put_row_rgb_RGB16; + fRenderBuffer->PutMonoRow = put_mono_row_RGB16; + fRenderBuffer->PutValues = put_values_RGB16; + fRenderBuffer->PutMonoValues = put_mono_values_RGB16; + break; + case B_RGB15: + fRenderBuffer->GetRow = get_row_RGB15; + fRenderBuffer->GetValues = get_values_RGB15; + fRenderBuffer->PutRow = put_row_RGB15; + fRenderBuffer->PutRowRGB = put_row_rgb_RGB15; + fRenderBuffer->PutMonoRow = put_mono_row_RGB15; + fRenderBuffer->PutValues = put_values_RGB15; + fRenderBuffer->PutMonoValues = put_mono_values_RGB15; + break; + case B_CMAP8: + fRenderBuffer->GetRow = get_row_CMAP8; + fRenderBuffer->GetValues = get_values_CMAP8; + fRenderBuffer->PutRow = put_row_CMAP8; + fRenderBuffer->PutRowRGB = put_row_rgb_CMAP8; + fRenderBuffer->PutMonoRow = put_mono_row_CMAP8; + fRenderBuffer->PutValues = put_values_CMAP8; + fRenderBuffer->PutMonoValues = put_mono_values_CMAP8; + break; + default: + fprintf(stderr, "unsupported screen color space %d\n", fColorSpace); + debugger("unsupported OpenGL color space"); + break; } - - _mesa_resize_framebuffer(fContext, fFrameBuffer, width, height); - fWidth = width; - fHeight = height; - fRenderBuffer->Data = fBitmap->Bits(); } + + fWidth = fNewWidth; + fHeight = fNewHeight; + + _AllocateBitmap(); } @@ -435,35 +437,45 @@ MesaSoftwareRenderer::SwapBuffers(bool VSync) // TODO: support VSync - if (fBitmap) { - if (fVisual->doubleBufferMode) - _mesa_notifySwapBuffers(fContext); + if (!fBitmap) + return; + if (fVisual->doubleBufferMode) + _mesa_notifySwapBuffers(fContext); - if (!fDirectModeEnabled || fInfo == NULL) { - GLView()->LockLooper(); + if (!fDirectModeEnabled || fInfo == NULL) { + if (GLView()->LockLooperWithTimeout(1000) == B_OK) { GLView()->DrawBitmap(fBitmap); GLView()->UnlockLooper(); - } else { - BAutolock lock(fInfoLocker); - uint8 bytesPerPixel = fInfo->bits_per_pixel / 8; - uint32 bytesPerRow = fBitmap->BytesPerRow(); - for (uint32 i = 0; i < fInfo->clip_list_count; i++) { - clipping_rect *clip = &fInfo->clip_list[i]; - int32 height = clip->bottom - clip->top + 1; - int32 bytesWidth - = (clip->right - clip->left + 1) * bytesPerPixel; - uint8 *p = (uint8 *)fInfo->bits + clip->top - * fInfo->bytes_per_row + clip->left * bytesPerPixel; - uint8 *b = (uint8 *)fBitmap->Bits() - + (clip->top - fInfo->window_bounds.top) * bytesPerRow - + (clip->left - fInfo->window_bounds.left) * bytesPerPixel; + } + return; + } - for (int y = 0; y < height; y++) { - memcpy(p, b, bytesWidth); - p += fInfo->bytes_per_row; - b += bytesPerRow; - } - } + BAutolock lock(fInfoLocker); + + // check the bitmap size still matches the size + if (fInfo->window_bounds.bottom - fInfo->window_bounds.top + != fBitmap->Bounds().IntegerHeight() + || fInfo->window_bounds.right - fInfo->window_bounds.left + != fBitmap->Bounds().IntegerWidth()) + return; + uint8 bytesPerPixel = fInfo->bits_per_pixel / 8; + uint32 bytesPerRow = fBitmap->BytesPerRow(); + for (uint32 i = 0; i < fInfo->clip_list_count; i++) { + clipping_rect *clip = &fInfo->clip_list[i]; + int32 height = clip->bottom - clip->top + 1; + int32 bytesWidth + = (clip->right - clip->left + 1) * bytesPerPixel; + uint8 *p = (uint8 *)fInfo->bits + clip->top + * fInfo->bytes_per_row + clip->left * bytesPerPixel; + uint8 *b = (uint8 *)fBitmap->Bits() + + (clip->top - fInfo->window_bounds.top) * bytesPerRow + + (clip->left - fInfo->window_bounds.left) + * bytesPerPixel; + + for (int y = 0; y < height; y++) { + memcpy(p, b, bytesWidth); + p += fInfo->bytes_per_row; + b += bytesPerRow; } } } @@ -579,6 +591,32 @@ MesaSoftwareRenderer::DirectConnected(direct_buffer_info *info) } +void +MesaSoftwareRenderer::FrameResized(float width, float height) +{ + BAutolock lock(fInfoLocker); + fNewWidth = (GLuint)width; + fNewHeight = (GLuint)height; +} + + +void +MesaSoftwareRenderer::_AllocateBitmap() +{ + // allocate new size of back buffer bitmap + delete fBitmap; + BRect rect(0.0, 0.0, fWidth - 1, fHeight - 1); + fBitmap = new BBitmap(rect, fColorSpace); + for (uint i = 0; i < fHeight; i++) { + fRowAddr[fHeight - i - 1] = (GLvoid *)((GLubyte *)fBitmap->Bits() + + i * fBitmap->BytesPerRow()); + } + + _mesa_resize_framebuffer(fContext, fFrameBuffer, fWidth, fHeight); + fRenderBuffer->Data = fBitmap->Bits(); +} + + // #pragma mark - static diff --git a/src/add-ons/opengl/mesa_software_renderer/MesaSoftwareRenderer.h b/src/add-ons/opengl/mesa_software_renderer/MesaSoftwareRenderer.h index 6109b4b641..bed7e89787 100644 --- a/src/add-ons/opengl/mesa_software_renderer/MesaSoftwareRenderer.h +++ b/src/add-ons/opengl/mesa_software_renderer/MesaSoftwareRenderer.h @@ -35,8 +35,9 @@ public: virtual void SwapBuffers(bool VSync = false); virtual void Draw(BRect updateRect); - virtual status_t CopyPixelsOut(BPoint source, BBitmap* dest); + virtual status_t CopyPixelsOut(BPoint source, BBitmap* dest); virtual status_t CopyPixelsIn(BBitmap* source, BPoint dest); + virtual void FrameResized(float width, float height); GLvoid** GetRows() { return fRowAddr; } @@ -60,6 +61,8 @@ private: GLuint width, GLuint height); static void Flush(GLcontext *ctx); + void _AllocateBitmap(); + BBitmap* fBitmap; bool fDirectModeEnabled; direct_buffer_info* fInfo; @@ -73,8 +76,8 @@ private: GLchan fClearColor[4]; // buffer clear color GLuint fClearIndex; // buffer clear color index - GLuint fWidth; - GLuint fHeight; + GLuint fWidth, fNewWidth; + GLuint fHeight, fNewHeight; color_space fColorSpace; GLvoid* fRowAddr[MAX_HEIGHT]; diff --git a/src/kits/opengl/GLView.cpp b/src/kits/opengl/GLView.cpp index 24a81e1d58..203d9a4c1d 100644 --- a/src/kits/opengl/GLView.cpp +++ b/src/kits/opengl/GLView.cpp @@ -84,8 +84,6 @@ BGLView::LockGL() { // TODO: acquire the OpenGL API lock it on this glview - if (!LockLooper()) - return; fDisplayLock.Lock(); if (fRenderer) fRenderer->LockGL(); @@ -95,13 +93,10 @@ BGLView::LockGL() void BGLView::UnlockGL() { - if (!fDisplayLock.IsLocked()) - return; - fDisplayLock.Unlock(); if (fRenderer) fRenderer->UnlockGL(); - UnlockLooper(); - + fDisplayLock.Unlock(); + // TODO: release the GL API lock to others glviews } @@ -137,7 +132,7 @@ BGLView::CopyPixelsOut(BPoint source, BBitmap *dest) if (!fRenderer) return B_ERROR; - if (! dest || ! dest->Bounds().IsValid()) + if (!dest || !dest->Bounds().IsValid()) return B_BAD_VALUE; return fRenderer->CopyPixelsOut(source, dest); @@ -150,7 +145,7 @@ BGLView::CopyPixelsIn(BBitmap *source, BPoint dest) if (!fRenderer) return B_ERROR; - if (! source || ! source->Bounds().IsValid()) + if (!source || !source->Bounds().IsValid()) return B_BAD_VALUE; return fRenderer->CopyPixelsIn(source, dest); @@ -211,6 +206,7 @@ BGLView::AttachedToWindow() #endif // Set default OpenGL viewport: glViewport(0, 0, Bounds().IntegerWidth(), Bounds().IntegerHeight()); + fRenderer->FrameResized(Bounds().IntegerWidth(), Bounds().IntegerHeight()); if (fClipInfo) { fRenderer->DirectConnected( @@ -263,8 +259,13 @@ BGLView::FrameResized(float width, float height) for (BView *v = this; v; v = v->Parent()) v->ConvertToParent(&fBounds); - if (fRenderer) + if (fRenderer) { + LockGL(); + _LockDraw(); fRenderer->FrameResized(width, height); + _UnlockDraw(); + UnlockGL(); + } BView::FrameResized(width, height); } @@ -344,6 +345,7 @@ BGLView::DirectConnected(direct_buffer_info *info) _UnlockDraw(); case B_DIRECT_MODIFY: { + _LockDraw(); localInfo->buffer_state = info->buffer_state; localInfo->driver_state = info->driver_state; localInfo->bits = info->bits; @@ -371,6 +373,7 @@ BGLView::DirectConnected(direct_buffer_info *info) for (uint32 c = 0; c < localInfo->clip_list_count; c++) localInfo->clip_list[c] = region.RectAtInt(c); + _UnlockDraw(); break; } case B_DIRECT_STOP: