src/video/bwindow/SDL_bframebuffer.cc
author Nathan Heisey <nathanheisey@gmail.com>
Sat, 20 Aug 2011 15:16:13 +0000
changeset 5938 b85b6326c498
parent 5936 116b7457e73a
child 5939 d9e9c343d264
permissions -rw-r--r--
Temporary mode-setting hack works
     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 = NULL;
   129 //			while(!bitmap) {
   130 				bitmap = bwin->GetBitmap();
   131 //			}
   132 			int32 windowPitch = bitmap->BytesPerRow();
   133 			int32 bufferPitch = bwin->GetRowBytes();
   134 			uint8 *windowpx;
   135 			uint8 *bufferpx;
   136 
   137 			int32 BPP = bwin->GetBytesPerPx();
   138 			int32 windowSub = bwin->GetFbX() * BPP +
   139 						  bwin->GetFbY() * windowPitch;
   140 			clipping_rect *clips = bwin->GetClips();
   141 			int32 numClips = bwin->GetNumClips();
   142 			int i, y;
   143 
   144 			/* Blit each clipping rectangle */
   145 			bscreen.WaitForRetrace();
   146 			for(i = 0; i < numClips; ++i) {
   147 				clipping_rect rc = clips[i];
   148 				/* Get addresses of the start of each clipping rectangle */
   149 				int32 width = clips[i].right - clips[i].left + 1;
   150 				int32 height = clips[i].bottom - clips[i].top + 1;
   151 				bufferpx = bwin->GetBufferPx() + 
   152 					clips[i].top * bufferPitch + clips[i].left * BPP;
   153 				windowpx = (uint8*)bitmap->Bits() + 
   154 					clips[i].top * windowPitch + clips[i].left * BPP -
   155 					windowSub;
   156 
   157 				/* Copy each row of pixels from the window buffer into the frame
   158 				   buffer */
   159 				for(y = 0; y < height; ++y)
   160 				{
   161 
   162 					if(bwin->CanTrashWindowBuffer()) {
   163 						goto escape;	/* Break out before the buffer is killed */
   164 					}
   165 
   166 //					printf("memcpy(0x%x, 0x%x, %i) ", bufferpx, windowpx, width * BPP);
   167 					memcpy(bufferpx, windowpx, width * BPP);
   168 					bufferpx += bufferPitch;
   169 					windowpx += windowPitch;
   170 				}
   171 //				printf("\t-\t");
   172 			}
   173 //			printf("\n");
   174 			bwin->SetBufferDirty(false);
   175 escape:
   176 			bwin->UnlockBuffer();
   177 		} else {
   178 			snooze(16000);
   179 		}
   180 	}
   181 	
   182 	return B_OK;
   183 }
   184 
   185 void BE_DestroyWindowFramebuffer(_THIS, SDL_Window * window) {
   186 	SDL_BWin *bwin = _ToBeWin(window);
   187 	
   188 	bwin->LockBuffer();
   189 	
   190 	/* Free and clear the window buffer */
   191 	BBitmap *bitmap = bwin->GetBitmap();
   192 	delete bitmap;
   193 	bwin->SetBitmap(NULL);
   194 	bwin->SetBufferExists(false);
   195 	bwin->UnlockBuffer();
   196 }
   197 
   198 
   199 /*
   200  * TODO:
   201  * This was written to test if certain errors were caused by threading issues.
   202  * The specific issues have since become rare enough that they may have been
   203  * solved, but I doubt it- they were pretty sporadic before now.
   204  */
   205 int32 BE_UpdateOnce(SDL_Window *window) {
   206 	SDL_BWin *bwin = _ToBeWin(window);
   207 	BScreen bscreen;
   208 	if(!bscreen.IsValid()) {
   209 		return -1;
   210 	}
   211 
   212 	if(bwin->ConnectionEnabled() && bwin->Connected()) {
   213 		bwin->LockBuffer();
   214 		int32 windowPitch = window->surface->pitch;
   215 		int32 bufferPitch = bwin->GetRowBytes();
   216 		uint8 *windowpx;
   217 		uint8 *bufferpx;
   218 
   219 		int32 BPP = bwin->GetBytesPerPx();
   220 		uint8 *windowBaseAddress = (uint8*)window->surface->pixels;
   221 		int32 windowSub = bwin->GetFbX() * BPP +
   222 						  bwin->GetFbY() * windowPitch;
   223 		clipping_rect *clips = bwin->GetClips();
   224 		int32 numClips = bwin->GetNumClips();
   225 		int i, y;
   226 
   227 		/* Blit each clipping rectangle */
   228 		bscreen.WaitForRetrace();
   229 		for(i = 0; i < numClips; ++i) {
   230 			clipping_rect rc = clips[i];
   231 			/* Get addresses of the start of each clipping rectangle */
   232 			int32 width = clips[i].right - clips[i].left + 1;
   233 			int32 height = clips[i].bottom - clips[i].top + 1;
   234 			bufferpx = bwin->GetBufferPx() + 
   235 				clips[i].top * bufferPitch + clips[i].left * BPP;
   236 			windowpx = windowBaseAddress + 
   237 				clips[i].top * windowPitch + clips[i].left * BPP - windowSub;
   238 
   239 			/* Copy each row of pixels from the window buffer into the frame
   240 			   buffer */
   241 			for(y = 0; y < height; ++y)
   242 			{
   243 				memcpy(bufferpx, windowpx, width * BPP);
   244 				bufferpx += bufferPitch;
   245 				windowpx += windowPitch;
   246 			}
   247 		}
   248 		bwin->UnlockBuffer();
   249 	}
   250 	return 0;
   251 }
   252 
   253 #ifdef __cplusplus
   254 }
   255 #endif