Moved draw code to a separate thread
authorNathan Heisey <nathanheisey@gmail.com>
Wed, 27 Jul 2011 11:06:38 +0000
changeset 5929 03298541cc4f
parent 5928 a3a52295bc0d
child 5930 a2372d470620
Moved draw code to a separate thread
src/main/beos/SDL_BApp.h
src/main/beos/SDL_BeApp.cc
src/video/bwindow/SDL_BWin.h
src/video/bwindow/SDL_bmodes.cc
src/video/bwindow/SDL_bmodes.h
--- a/src/main/beos/SDL_BApp.h	Tue Jul 26 17:48:40 2011 +0000
+++ b/src/main/beos/SDL_BApp.h	Wed Jul 27 11:06:38 2011 +0000
@@ -37,6 +37,7 @@
 /* Local includes */
 #include "../../events/SDL_events_c.h"
 #include "../../video/bwindow/SDL_bkeyboard.h"
+#include "../../video/bwindow/SDL_bmodes.h"
 
 #ifdef __cplusplus
 }
@@ -167,7 +168,7 @@
     int32 GetID(SDL_Window *win) {
     	int32 i;
     	for(i = 0; i < _GetNumWindowSlots(); ++i) {
-    		if( _GetSDLWindow(i) == NULL ) {
+    		if( GetSDLWindow(i) == NULL ) {
     			_SetSDLWindow(win, i);
     			return i;
     		}
@@ -189,6 +190,11 @@
        there another way to do this? */
     void ClearID(SDL_BWin *bwin); /* Defined in SDL_BeApp.cc */
     
+    
+	SDL_Window *GetSDLWindow(int32 winID) {
+		return window_map[winID];
+	}
+    
 private:
 	/* Event management */
 	void _HandleBasicWindowEvent(BMessage *msg, int32 sdlEventType) {
@@ -199,7 +205,7 @@
 		) {
 			return;
 		}
-		win = _GetSDLWindow(winID);
+		win = GetSDLWindow(winID);
 		SDL_SendWindowEvent(win, sdlEventType, 0, 0);
 	}
 	
@@ -214,8 +220,11 @@
 		) {
 			return;
 		}
-		win = _GetSDLWindow(winID);
+		win = GetSDLWindow(winID);
 		SDL_SendMouseMotion(win, 0, x, y);
+		
+		/* FIXME: Attempt at fixing rendering problems */
+		BE_UpdateWindowFramebuffer(NULL,win,NULL,-1);
 	}
 	
 	void _HandleMouseButton(BMessage *msg) {
@@ -229,7 +238,7 @@
 		) {
 			return;
 		}
-		win = _GetSDLWindow(winID);
+		win = GetSDLWindow(winID);
 		SDL_SendMouseButton(win, state, button);
 	}
 	
@@ -244,7 +253,7 @@
 		) {
 			return;
 		}
-		win = _GetSDLWindow(winID);
+		win = GetSDLWindow(winID);
 		SDL_SendMouseWheel(win, xTicks, yTicks);
 	}
 	
@@ -275,7 +284,7 @@
 		) {
 			return;
 		}
-		win = _GetSDLWindow(winID);
+		win = GetSDLWindow(winID);
 		if(bSetFocus) {
 			SDL_SetMouseFocus(win);
 		} else if(SDL_GetMouseFocus() == win) {
@@ -294,7 +303,7 @@
 		) {
 			return;
 		}
-		win = _GetSDLWindow(winID);
+		win = GetSDLWindow(winID);
 		if(bSetFocus) {
 			SDL_SetKeyboardFocus(win);
 		} else if(SDL_GetKeyboardFocus() == win) {
@@ -315,8 +324,11 @@
 		) {
 			return;
 		}
-		win = _GetSDLWindow(winID);
+		win = GetSDLWindow(winID);
 		SDL_SendWindowEvent(win, SDL_WINDOWEVENT_MOVED, xPos, yPos);
+		
+		/* FIXME: Attempt at fixing rendering problems */
+		BE_UpdateWindowFramebuffer(NULL,win,NULL,-1);
 	}
 	
 	void _HandleWindowResized(BMessage *msg) {
@@ -331,8 +343,11 @@
 		) {
 			return;
 		}
-		win = _GetSDLWindow(winID);
+		win = GetSDLWindow(winID);
 		SDL_SendWindowEvent(win, SDL_WINDOWEVENT_RESIZED, w, h);
+		
+		/* FIXME: Attempt at fixing rendering problems */
+		BE_UpdateWindowFramebuffer(NULL,win,NULL,-1);
 	}
 
 	bool _GetWinID(BMessage *msg, int32 *winID) {
@@ -342,10 +357,6 @@
 
 
 	/* Vector imitators */
-	SDL_Window *_GetSDLWindow(int32 winID) {
-		return window_map[winID];
-	}
-	
 	void _SetSDLWindow(SDL_Window *win, int32 winID) {
 		window_map[winID] = win;
 	}
--- a/src/main/beos/SDL_BeApp.cc	Tue Jul 26 17:48:40 2011 +0000
+++ b/src/main/beos/SDL_BeApp.cc	Wed Jul 27 11:06:38 2011 +0000
@@ -126,7 +126,7 @@
 void SDL_BApp::ClearID(SDL_BWin *bwin) {
 	_SetSDLWindow(NULL, bwin->GetID());
 	int32 i = _GetNumWindowSlots() - 1;
-	while(i >= 0 && _GetSDLWindow(i) == NULL) {
+	while(i >= 0 && GetSDLWindow(i) == NULL) {
 		_PopBackWindow();
 		--i;
 	}
--- a/src/video/bwindow/SDL_BWin.h	Tue Jul 26 17:48:40 2011 +0000
+++ b/src/video/bwindow/SDL_BWin.h	Wed Jul 27 11:06:38 2011 +0000
@@ -76,9 +76,14 @@
 
         /* Handle framebuffer stuff */
         _connected = _connection_disabled = false;
+        _buffer_created = _buffer_dirty = false;
         _trash__window_buffer = false;
         _buffer_locker = new BLocker();
         _window_buffer = NULL;
+        
+        _draw_thread_id = spawn_thread(BE_DrawThread, "drawing_thread",
+        					B_NORMAL_PRIORITY, (void*) this);
+        resume_thread(_draw_thread_id);
 //        LockBuffer();	/* Unlocked by buffer initialization */
     }
 
@@ -86,6 +91,7 @@
     {
         Lock();
         _connection_disabled = true;
+        int32 result;
         
 #if SDL_VIDEO_OPENGL
         if (_SDL_GLView) {
@@ -102,6 +108,7 @@
         
         /* Clean up framebuffer stuff */
         _buffer_locker->Lock();
+        wait_for_thread(_draw_thread_id, &result);
         free(_clips);
         delete _buffer_locker;
     }
@@ -382,8 +389,6 @@
 	/* Accessor methods */
 	bool IsShown() { return _shown; }
 	int32 GetID() { return _id; }
-	void LockBuffer() {	_buffer_locker->Lock(); }
-	void UnlockBuffer() { _buffer_locker->Unlock(); }
 	uint32 GetRowBytes() { return _row_bytes; }
 	int32 GetFbX() { return _bounds.left; }
 	int32 GetFbY() { return _bounds.top; }
@@ -395,12 +400,18 @@
 	int32 GetNumClips() { return _num_clips; }
 	uint8* GetBufferPx() { return _bits; }
 	int32 GetBytesPerPx() { return _bytes_per_px; }
-	void SetWindowFramebuffer(uint8* fb) { _window_buffer = fb; }
 	uint8* GetWindowFramebuffer() { return _window_buffer; }
 	bool CanTrashWindowBuffer() { return _trash__window_buffer; }
+	bool BufferExists() { return _buffer_created; }
+	bool BufferIsDirty() { return _buffer_dirty; }
 	
 	/* Setter methods */
 	void SetID(int32 id) { _id = id; }
+	bool SetBufferExists(bool bufferExists) { _buffer_created = bufferExists; }
+	void SetWindowFramebuffer(uint8* fb) { _window_buffer = fb; }
+	void LockBuffer() {	_buffer_locker->Lock(); }
+	void UnlockBuffer() { _buffer_locker->Unlock(); }
+	void SetBufferDirty(bool bufferDirty) { _buffer_dirty = bufferDirty; }
 
 
 
@@ -416,10 +427,6 @@
     {
         return (_the_view);
     }
-
-	
-	
-	
 	
 	
 	
@@ -584,7 +591,10 @@
     BRect *_prev_frame;	/* Previous position and size of the window */
     
     /* Framebuffer members */
-    bool			_connected, _connection_disabled;
+    bool			_connected,
+    				_connection_disabled,
+    				_buffer_created,
+    				_buffer_dirty;
     uint8		   *_bits;
     uint32			_row_bytes;
     clipping_rect	_bounds;
@@ -594,6 +604,7 @@
     int32			_bytes_per_px;
     uint8		   *_window_buffer;	/* A copy of the window buffer */
     bool			_trash__window_buffer;
+    thread_id		_draw_thread_id;
 };
 
 #endif
--- a/src/video/bwindow/SDL_bmodes.cc	Tue Jul 26 17:48:40 2011 +0000
+++ b/src/video/bwindow/SDL_bmodes.cc	Wed Jul 27 11:06:38 2011 +0000
@@ -218,7 +218,7 @@
 		return -1;
 	}
 	
-	while(!bwin->Connected()) { snooze(10); }
+	while(!bwin->Connected()) { snooze(100); }
 
 	/* Make sure we have exclusive access to frame buffer data */
 	bwin->LockBuffer();
@@ -243,6 +243,7 @@
 		bwin->SetWindowFramebuffer((uint8*)(*pixels));
 	}
 
+	bwin->SetBufferExists(true);
 	bwin->UnlockBuffer();
 	return 0;
 }
@@ -251,51 +252,72 @@
 
 int BE_UpdateWindowFramebuffer(_THIS, SDL_Window * window,
                                       SDL_Rect * rects, int numrects) {
+	if(!window)
+		return 0;
+
 	SDL_BWin *bwin = _ToBeWin(window);
+	
+	bwin->LockBuffer();
+	bwin->SetBufferDirty(true);
+	bwin->UnlockBuffer();
+
+	return 0;
+}
+
+int32 BE_DrawThread(void *data) {
+	SDL_BWin *bwin = (SDL_BWin*)data;
+	SDL_Window *window = _GetBeApp()->GetSDLWindow(bwin->GetID());
+	
 	BScreen bscreen;
 	if(!bscreen.IsValid()) {
 		return -1;
 	}
 
-	if(bwin->ConnectionEnabled() && bwin->Connected()) {
-		bwin->LockBuffer();
-		int32 windowPitch = window->surface->pitch;
-		int32 bufferPitch = bwin->GetRowBytes();
-		uint8 *windowpx;
-		uint8 *bufferpx;
+	while(bwin->ConnectionEnabled()) {
+		if( bwin->Connected() && bwin->BufferExists() && bwin->BufferIsDirty() ) {
+			bwin->LockBuffer();
+			int32 windowPitch = window->surface->pitch;
+			int32 bufferPitch = bwin->GetRowBytes();
+			uint8 *windowpx;
+			uint8 *bufferpx;
 
-		int32 BPP = bwin->GetBytesPerPx();
-		uint8 *windowBaseAddress = (uint8*)window->surface->pixels;
-		int32 windowSub = bwin->GetFbX() * BPP +
+			int32 BPP = bwin->GetBytesPerPx();
+			uint8 *windowBaseAddress = (uint8*)window->surface->pixels;
+			int32 windowSub = bwin->GetFbX() * BPP +
 						  bwin->GetFbY() * windowPitch;
-		clipping_rect *clips = bwin->GetClips();
-		int32 numClips = bwin->GetNumClips();
-		int i, y;
+			clipping_rect *clips = bwin->GetClips();
+			int32 numClips = bwin->GetNumClips();
+			int i, y;
 
-		/* Blit each clipping rectangle */
-		bscreen.WaitForRetrace();
-		for(i = 0; i < numClips; ++i) {
-			clipping_rect rc = clips[i];
-			/* Get addresses of the start of each clipping rectangle */
-			int32 width = clips[i].right - clips[i].left + 1;
-			int32 height = clips[i].bottom - clips[i].top + 1;
-			bufferpx = bwin->GetBufferPx() + 
-				clips[i].top * bufferPitch + clips[i].left * BPP;
-			windowpx = windowBaseAddress + 
-				clips[i].top * windowPitch + clips[i].left * BPP - windowSub;
+			/* Blit each clipping rectangle */
+			bscreen.WaitForRetrace();
+			for(i = 0; i < numClips; ++i) {
+				clipping_rect rc = clips[i];
+				/* Get addresses of the start of each clipping rectangle */
+				int32 width = clips[i].right - clips[i].left + 1;
+				int32 height = clips[i].bottom - clips[i].top + 1;
+				bufferpx = bwin->GetBufferPx() + 
+					clips[i].top * bufferPitch + clips[i].left * BPP;
+				windowpx = windowBaseAddress + 
+					clips[i].top * windowPitch + clips[i].left * BPP - windowSub;
 
-			/* Copy each row of pixels from the window buffer into the frame
-			   buffer */
-			for(y = 0; y < height; ++y)
-			{
-				memcpy(bufferpx, windowpx, width * BPP);
-				bufferpx += bufferPitch;
-				windowpx += windowPitch;
+				/* Copy each row of pixels from the window buffer into the frame
+				   buffer */
+				for(y = 0; y < height; ++y)
+				{
+					memcpy(bufferpx, windowpx, width * BPP);
+					bufferpx += bufferPitch;
+					windowpx += windowPitch;
+				}
 			}
+			bwin->SetBufferDirty(false);
+			bwin->UnlockBuffer();
+		} else {
+			snooze(1000);
 		}
-		bwin->UnlockBuffer();
 	}
-	return 0;
+	
+	return B_OK;
 }
 
 void BE_DestroyWindowFramebuffer(_THIS, SDL_Window * window) {
@@ -307,6 +329,7 @@
 	uint8* winBuffer = bwin->GetWindowFramebuffer();
 	SDL_free(winBuffer);
 	bwin->SetWindowFramebuffer(NULL);
+	bwin->SetBufferExists(false);
 	bwin->UnlockBuffer();
 }
 
--- a/src/video/bwindow/SDL_bmodes.h	Tue Jul 26 17:48:40 2011 +0000
+++ b/src/video/bwindow/SDL_bmodes.h	Wed Jul 27 11:06:38 2011 +0000
@@ -42,6 +42,7 @@
 extern int BE_UpdateWindowFramebuffer(_THIS, SDL_Window * window,
                                        SDL_Rect * rects, int numrects);
 extern void BE_DestroyWindowFramebuffer(_THIS, SDL_Window * window);
+extern int32 BE_DrawThread(void *data);
 
 
 #ifdef __cplusplus