src/video/bwindow/SDL_bframebuffer.cc
author Nathan Heisey <nathanheisey@gmail.com>
Fri, 12 Aug 2011 16:58:54 +0000
changeset 5936 116b7457e73a
parent 5934 01531d8d1e01
child 5938 b85b6326c498
permissions -rw-r--r--
Reduced SEGFAULT occurence on resize?
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 
    22 #include "SDL_bframebuffer.h"
    23 
    24 #include <AppKit.h>
    25 #include <InterfaceKit.h>
    26 #include "SDL_bmodes.h"
    27 #include "SDL_BWin.h"
    28 
    29 #include "../../main/beos/SDL_BApp.h"
    30 
    31 #ifdef __cplusplus
    32 extern "C" {
    33 #endif
    34 
    35 int32 BE_UpdateOnce(SDL_Window *window);
    36 
    37 static inline SDL_BWin *_ToBeWin(SDL_Window *window) {
    38 	return ((SDL_BWin*)(window->driverdata));
    39 }
    40 
    41 static inline SDL_BApp *_GetBeApp() {
    42 	return ((SDL_BApp*)be_app);
    43 }
    44 
    45 int BE_CreateWindowFramebuffer(_THIS, SDL_Window * window,
    46                                        Uint32 * format,
    47                                        void ** pixels, int *pitch) {
    48 	SDL_BWin *bwin = _ToBeWin(window);
    49 	BScreen bscreen;
    50 	if(!bscreen.IsValid()) {
    51 		return -1;
    52 	}
    53 
    54 	while(!bwin->Connected()) { snooze(100); }
    55 	
    56 	/* Make sure we have exclusive access to frame buffer data */
    57 	bwin->LockBuffer();
    58 
    59 	/* format */
    60 	display_mode bmode;
    61 	bscreen.GetMode(&bmode);
    62 	int32 bpp = ColorSpaceToBitsPerPixel(bmode.space);
    63 	*format = BPPToSDLPxFormat(bpp);
    64 
    65 	/* Create the new bitmap object */
    66 	BBitmap *bitmap = bwin->GetBitmap();
    67 
    68 	if(bitmap) {
    69 		delete bitmap;
    70 	}
    71 	bitmap = new BBitmap(bwin->Bounds(), (color_space)bmode.space,
    72 			false,	/* Views not accepted */
    73 			true);	/* Contiguous memory required */
    74 			
    75 	if(bitmap->InitCheck() != B_OK) {
    76 		SDL_SetError("Could not initialize back buffer!\n");
    77 		return -1;
    78 	}
    79 
    80 
    81 	bwin->SetBitmap(bitmap);
    82 	
    83 	/* Set the pixel pointer */
    84 	*pixels = bitmap->Bits();
    85 
    86 	/* pitch = width of window, in bytes */
    87 	*pitch = bitmap->BytesPerRow();
    88 
    89 	bwin->SetBufferExists(true);
    90 	bwin->SetTrashBuffer(false);
    91 	bwin->UnlockBuffer();
    92 	return 0;
    93 }
    94 
    95 
    96 
    97 int BE_UpdateWindowFramebuffer(_THIS, SDL_Window * window,
    98                                       SDL_Rect * rects, int numrects) {
    99 	if(!window)
   100 		return 0;
   101 
   102 	SDL_BWin *bwin = _ToBeWin(window);
   103 
   104 #ifdef DRAWTHREAD	
   105 	bwin->LockBuffer();
   106 	bwin->SetBufferDirty(true);
   107 	bwin->UnlockBuffer();
   108 #else
   109 	bwin->SetBufferDirty(true);
   110 	BE_UpdateOnce(window);
   111 #endif
   112 
   113 	return 0;
   114 }
   115 
   116 int32 BE_DrawThread(void *data) {
   117 	SDL_BWin *bwin = (SDL_BWin*)data;
   118 	SDL_Window *window = _GetBeApp()->GetSDLWindow(bwin->GetID());
   119 	
   120 	BScreen bscreen;
   121 	if(!bscreen.IsValid()) {
   122 		return -1;
   123 	}
   124 
   125 	while(bwin->ConnectionEnabled()) {
   126 		if( bwin->Connected() && bwin->BufferExists() && bwin->BufferIsDirty() ) {
   127 			bwin->LockBuffer();
   128 			BBitmap *bitmap = bwin->GetBitmap();
   129 			int32 windowPitch = bitmap->BytesPerRow();
   130 			int32 bufferPitch = bwin->GetRowBytes();
   131 			uint8 *windowpx;
   132 			uint8 *bufferpx;
   133 
   134 			int32 BPP = bwin->GetBytesPerPx();
   135 			int32 windowSub = bwin->GetFbX() * BPP +
   136 						  bwin->GetFbY() * windowPitch;
   137 			clipping_rect *clips = bwin->GetClips();
   138 			int32 numClips = bwin->GetNumClips();
   139 			int i, y;
   140 
   141 			/* Blit each clipping rectangle */
   142 			bscreen.WaitForRetrace();
   143 			for(i = 0; i < numClips; ++i) {
   144 				clipping_rect rc = clips[i];
   145 				/* Get addresses of the start of each clipping rectangle */
   146 				int32 width = clips[i].right - clips[i].left + 1;
   147 				int32 height = clips[i].bottom - clips[i].top + 1;
   148 				bufferpx = bwin->GetBufferPx() + 
   149 					clips[i].top * bufferPitch + clips[i].left * BPP;
   150 				windowpx = (uint8*)bitmap->Bits() + 
   151 					clips[i].top * windowPitch + clips[i].left * BPP -
   152 					windowSub;
   153 
   154 				/* Copy each row of pixels from the window buffer into the frame
   155 				   buffer */
   156 				for(y = 0; y < height; ++y)
   157 				{
   158 
   159 					if(bwin->CanTrashWindowBuffer()) {
   160 						goto escape;	/* Break out before the buffer is killed */
   161 					}
   162 
   163 //					printf("memcpy(0x%x, 0x%x, %i) ", bufferpx, windowpx, width * BPP);
   164 					memcpy(bufferpx, windowpx, width * BPP);
   165 					bufferpx += bufferPitch;
   166 					windowpx += windowPitch;
   167 				}
   168 //				printf("\t-\t");
   169 			}
   170 //			printf("\n");
   171 			bwin->SetBufferDirty(false);
   172 escape:
   173 			bwin->UnlockBuffer();
   174 		} else {
   175 			snooze(16000);
   176 		}
   177 	}
   178 	
   179 	return B_OK;
   180 }
   181 
   182 void BE_DestroyWindowFramebuffer(_THIS, SDL_Window * window) {
   183 	SDL_BWin *bwin = _ToBeWin(window);
   184 	
   185 	bwin->LockBuffer();
   186 	
   187 	/* Free and clear the window buffer */
   188 	BBitmap *bitmap = bwin->GetBitmap();
   189 	delete bitmap;
   190 	bwin->SetBitmap(NULL);
   191 	bwin->SetBufferExists(false);
   192 	bwin->UnlockBuffer();
   193 }
   194 
   195 
   196 int32 BE_UpdateOnce(SDL_Window *window) {
   197 	SDL_BWin *bwin = _ToBeWin(window);
   198 	BScreen bscreen;
   199 	if(!bscreen.IsValid()) {
   200 		return -1;
   201 	}
   202 
   203 	if(bwin->ConnectionEnabled() && bwin->Connected()) {
   204 		bwin->LockBuffer();
   205 		int32 windowPitch = window->surface->pitch;
   206 		int32 bufferPitch = bwin->GetRowBytes();
   207 		uint8 *windowpx;
   208 		uint8 *bufferpx;
   209 
   210 		int32 BPP = bwin->GetBytesPerPx();
   211 		uint8 *windowBaseAddress = (uint8*)window->surface->pixels;
   212 		int32 windowSub = bwin->GetFbX() * BPP +
   213 						  bwin->GetFbY() * windowPitch;
   214 		clipping_rect *clips = bwin->GetClips();
   215 		int32 numClips = bwin->GetNumClips();
   216 		int i, y;
   217 
   218 		/* Blit each clipping rectangle */
   219 		bscreen.WaitForRetrace();
   220 		for(i = 0; i < numClips; ++i) {
   221 			clipping_rect rc = clips[i];
   222 			/* Get addresses of the start of each clipping rectangle */
   223 			int32 width = clips[i].right - clips[i].left + 1;
   224 			int32 height = clips[i].bottom - clips[i].top + 1;
   225 			bufferpx = bwin->GetBufferPx() + 
   226 				clips[i].top * bufferPitch + clips[i].left * BPP;
   227 			windowpx = windowBaseAddress + 
   228 				clips[i].top * windowPitch + clips[i].left * BPP - windowSub;
   229 
   230 			/* Copy each row of pixels from the window buffer into the frame
   231 			   buffer */
   232 			for(y = 0; y < height; ++y)
   233 			{
   234 				memcpy(bufferpx, windowpx, width * BPP);
   235 				bufferpx += bufferPitch;
   236 				windowpx += windowPitch;
   237 			}
   238 		}
   239 		bwin->UnlockBuffer();
   240 	}
   241 	return 0;
   242 }
   243 
   244 #ifdef __cplusplus
   245 }
   246 #endif