src/video/bwindow/SDL_bframebuffer.cc
author Sam Lantinga <slouken@libsdl.org>
Mon, 31 Oct 2011 05:56:58 -0400
changeset 6044 35448a5ea044
parent 6037 2feab4874268
child 6138 4c64952a58fb
permissions -rw-r--r--
Lots of fixes importing SDL source wholesale into a new iOS project
     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 #include "SDL_config.h"
    22 
    23 #if SDL_VIDEO_DRIVER_BWINDOW
    24 
    25 #include "SDL_bframebuffer.h"
    26 
    27 #include <AppKit.h>
    28 #include <InterfaceKit.h>
    29 #include "SDL_bmodes.h"
    30 #include "SDL_BWin.h"
    31 
    32 #include "../../main/beos/SDL_BApp.h"
    33 
    34 #ifdef __cplusplus
    35 extern "C" {
    36 #endif
    37 
    38 int32 BE_UpdateOnce(SDL_Window *window);
    39 
    40 static inline SDL_BWin *_ToBeWin(SDL_Window *window) {
    41 	return ((SDL_BWin*)(window->driverdata));
    42 }
    43 
    44 static inline SDL_BApp *_GetBeApp() {
    45 	return ((SDL_BApp*)be_app);
    46 }
    47 
    48 int BE_CreateWindowFramebuffer(_THIS, SDL_Window * window,
    49                                        Uint32 * format,
    50                                        void ** pixels, int *pitch) {
    51 	SDL_BWin *bwin = _ToBeWin(window);
    52 	BScreen bscreen;
    53 	if(!bscreen.IsValid()) {
    54 		return -1;
    55 	}
    56 
    57 	while(!bwin->Connected()) { snooze(100); }
    58 	
    59 	/* Make sure we have exclusive access to frame buffer data */
    60 	bwin->LockBuffer();
    61 
    62 	/* format */
    63 	display_mode bmode;
    64 	bscreen.GetMode(&bmode);
    65 	int32 bpp = BE_ColorSpaceToBitsPerPixel(bmode.space);
    66 	*format = BE_BPPToSDLPxFormat(bpp);
    67 
    68 	/* Create the new bitmap object */
    69 	BBitmap *bitmap = bwin->GetBitmap();
    70 
    71 	if(bitmap) {
    72 		delete bitmap;
    73 	}
    74 	bitmap = new BBitmap(bwin->Bounds(), (color_space)bmode.space,
    75 			false,	/* Views not accepted */
    76 			true);	/* Contiguous memory required */
    77 			
    78 	if(bitmap->InitCheck() != B_OK) {
    79 		SDL_SetError("Could not initialize back buffer!\n");
    80 		return -1;
    81 	}
    82 
    83 
    84 	bwin->SetBitmap(bitmap);
    85 	
    86 	/* Set the pixel pointer */
    87 	*pixels = bitmap->Bits();
    88 
    89 	/* pitch = width of window, in bytes */
    90 	*pitch = bitmap->BytesPerRow();
    91 
    92 	bwin->SetBufferExists(true);
    93 	bwin->SetTrashBuffer(false);
    94 	bwin->UnlockBuffer();
    95 	return 0;
    96 }
    97 
    98 
    99 
   100 int BE_UpdateWindowFramebuffer(_THIS, SDL_Window * window,
   101                                       SDL_Rect * rects, int numrects) {
   102 	if(!window)
   103 		return 0;
   104 
   105 	SDL_BWin *bwin = _ToBeWin(window);
   106 
   107 #ifdef DRAWTHREAD	
   108 	bwin->LockBuffer();
   109 	bwin->SetBufferDirty(true);
   110 	bwin->UnlockBuffer();
   111 #else
   112 	bwin->SetBufferDirty(true);
   113 	BE_UpdateOnce(window);
   114 #endif
   115 
   116 	return 0;
   117 }
   118 
   119 int32 BE_DrawThread(void *data) {
   120 	SDL_BWin *bwin = (SDL_BWin*)data;
   121 	
   122 	BScreen bscreen;
   123 	if(!bscreen.IsValid()) {
   124 		return -1;
   125 	}
   126 
   127 	while(bwin->ConnectionEnabled()) {
   128 		if( bwin->Connected() && bwin->BufferExists() && bwin->BufferIsDirty() ) {
   129 			bwin->LockBuffer();
   130 			BBitmap *bitmap = NULL;
   131 			bitmap = bwin->GetBitmap();
   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 					memcpy(bufferpx, windowpx, width * BPP);
   167 					bufferpx += bufferPitch;
   168 					windowpx += windowPitch;
   169 				}
   170 			}
   171 
   172 			bwin->SetBufferDirty(false);
   173 escape:
   174 			bwin->UnlockBuffer();
   175 		} else {
   176 			snooze(16000);
   177 		}
   178 	}
   179 	
   180 	return B_OK;
   181 }
   182 
   183 void BE_DestroyWindowFramebuffer(_THIS, SDL_Window * window) {
   184 	SDL_BWin *bwin = _ToBeWin(window);
   185 	
   186 	bwin->LockBuffer();
   187 	
   188 	/* Free and clear the window buffer */
   189 	BBitmap *bitmap = bwin->GetBitmap();
   190 	delete bitmap;
   191 	bwin->SetBitmap(NULL);
   192 	bwin->SetBufferExists(false);
   193 	bwin->UnlockBuffer();
   194 }
   195 
   196 
   197 /*
   198  * TODO:
   199  * This was written to test if certain errors were caused by threading issues.
   200  * The specific issues have since become rare enough that they may have been
   201  * solved, but I doubt it- they were pretty sporadic before now.
   202  */
   203 int32 BE_UpdateOnce(SDL_Window *window) {
   204 	SDL_BWin *bwin = _ToBeWin(window);
   205 	BScreen bscreen;
   206 	if(!bscreen.IsValid()) {
   207 		return -1;
   208 	}
   209 
   210 	if(bwin->ConnectionEnabled() && bwin->Connected()) {
   211 		bwin->LockBuffer();
   212 		int32 windowPitch = window->surface->pitch;
   213 		int32 bufferPitch = bwin->GetRowBytes();
   214 		uint8 *windowpx;
   215 		uint8 *bufferpx;
   216 
   217 		int32 BPP = bwin->GetBytesPerPx();
   218 		uint8 *windowBaseAddress = (uint8*)window->surface->pixels;
   219 		int32 windowSub = bwin->GetFbX() * BPP +
   220 						  bwin->GetFbY() * windowPitch;
   221 		clipping_rect *clips = bwin->GetClips();
   222 		int32 numClips = bwin->GetNumClips();
   223 		int i, y;
   224 
   225 		/* Blit each clipping rectangle */
   226 		bscreen.WaitForRetrace();
   227 		for(i = 0; i < numClips; ++i) {
   228 			clipping_rect rc = clips[i];
   229 			/* Get addresses of the start of each clipping rectangle */
   230 			int32 width = clips[i].right - clips[i].left + 1;
   231 			int32 height = clips[i].bottom - clips[i].top + 1;
   232 			bufferpx = bwin->GetBufferPx() + 
   233 				clips[i].top * bufferPitch + clips[i].left * BPP;
   234 			windowpx = windowBaseAddress + 
   235 				clips[i].top * windowPitch + clips[i].left * BPP - windowSub;
   236 
   237 			/* Copy each row of pixels from the window buffer into the frame
   238 			   buffer */
   239 			for(y = 0; y < height; ++y)
   240 			{
   241 				memcpy(bufferpx, windowpx, width * BPP);
   242 				bufferpx += bufferPitch;
   243 				windowpx += windowPitch;
   244 			}
   245 		}
   246 		bwin->UnlockBuffer();
   247 	}
   248 	return 0;
   249 }
   250 
   251 #ifdef __cplusplus
   252 }
   253 #endif
   254 
   255 #endif /* SDL_VIDEO_DRIVER_BWINDOW */